Should the getter on line [1] return a reference to ConnectionStatus as well? |
In most cases, a "getter" function
should not return a non-
const
reference, because
leaking a non-
const
references to "internal" data is usually undesired. It would allow the caller to
modify "internal" data (via the reference)
without using the "setter" function!
Returning a
const
reference from a "getter" function
can make sense, e.g. if the data to be return is big and you don't want to return a
copy. But, in this case, you are just returning a simple
enum
value (eseentially an
int
), so returning a reference doesn't make much sense.
In cases where you
do return a non-
const
reference from your "getter" function – typically a reference to some sort of "nested" object that you explicitly
do want the caller to be able to modify – a separate "setter" function is
not needed and wouldn't make much sense!
I think you should change your code like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
enum ConnectionStatus
{
Disconnected,
Connected
};
class Status
{
public:
inline ConnectionStatus getConnectionStatus() const // <-- return current status "by value"
{
return connectionStatus;
}
inline void setConnectionStatus(const ConnectionStatus val)
{
if ((val != Connected) && (val != Disconnected)) {
std::abort(); // <-- input validation: protect us from "rogue" value
}
connectionStatus = val;
}
private:
ConnectionStatus connectionStatus = ConnectionStatus::Disconnected;
};
class Foo
{
public:
inline Status &getStatus() // <-- return mutable (non-const) reference to "inner" Status object
{
return status;
}
private:
Status status;
};
int main()
{
Foo foo;
std::cout << "Init Connection Status: " << foo.getStatus().getConnectionStatus() << std::endl;
foo.getStatus().setConnectionStatus(ConnectionStatus::Connected);
std::cout << "After setting status: " << foo.getStatus().getConnectionStatus() << std::endl;
// foo.getStatus().setConnectionStatus((ConnectionStatus)42);
return 0;
}
| |
Works as expected:
Init Connection Status: 0
After setting status: 1 |
Don't make your life harder than necessary. When you have both setter and getter your member variable is basically public just with overhead. |
Well, that's debatable. Many people think it's a good practice to use "getter" and "setter" functions in the public interface of your class, even if they do
not contain any additional logic
yet, and keep your member variables
private. For example, you may want to add
input validation to your "setter" function(s) at a later time (e.g. to ensure that only "valid" data will be written into the member variable), and that would
not be possible if the member variables were
public. Making the member variable(s)
private later potentially breaks a lot of existing code...
(As for the performance, the compiler is almost certainly going to
inline the getter/setter code anyway, even
without the
inline
directive)