We can all agree on public variables being bad for encapsulation and all that. However, I noticed a lot of code that does this type of stuff:
class foo {
private:
int integer_;
string someString_;
// other variables
public:
int& integer() { return integer_; }
string& someString() { return someString_; }
// other "functions"
}
int main() {
foo f;
f.integer() = 10;
f.someString() = "something";
return 0;
}
I have seen this being used in many places and I don't get why. Basically it returns a reference to the data and thus exposes it directly to the outside. So encapsulation is not really achieved, not from any perspective.
Why is this commonly used?
I have to partially disagree both with @πάνταῥεῖ and @Rakete1111 's answers, considering how a class's definition is something that may evolve over time.
While it's true that, often, these getter methods are written by someone who's just heard the "no exposing members" mantra, they can also have legitimate uses:
vector<bool>
works; when you call itsoperator[]
you don't get aboolean&
, you get some kind of proxy which, when assigned or assigned-to, does the appropriate bit extraction or setting.To sum up: The "dummy" non-const-reference getter can be a stub for other, meaningful, code.
That being said, it is often a good idea to just make the getter return a const reference or a value. Or just exposing the field in those cases where it's appropriate (and there are some of those too).
There's a recurring mantra, that getter/setter functions should be used to encapsulate your data. Hence many (unexperienced or coffee-overloaded) programmers get the idea they should use something like:
but that isn't much different from simply writing:
Well, it adds a function call, but you cannot control what the client does with the reference.
If you really want to provide a getter function write:
A corresponding setter function looks like:
This construction may be used for debugging purposes.
If you have a public variable, you can't monitor its usage easily. Converting it to a pair of private variable and method-returning reference will allow you to put a breakpoint and/or log the calls.
However, separate getter and setter would serve the same purpose even better, so this is just an advantage over plain public variables.
I would strongly discouraged returning a non-const reference to a private variable. Not because it breaks encapsulation, but because it is unnecessary: Why not make the variable
public
in the first place?Breaking encapsulation is bad, yes, but that does not mean that every variable should be
private
. Some variables are meant to be read and modified from the user, so it would make sense to make thempublic
. For example, takestd::pair
, it has 2 public member variables,first
andsecond
. That's not bad practice.The only time it doesn't make sense is when the variable is not supposed to be written to. That would be bad, as it would actually break encapsulation and make the whole program hard to debug.
I wrote this once. I planned later to go back and replace the field getter with something that returned a stack object to something that could be cast to the original type and assigned to by the original type. This allowed me to go back later and intercept all assignments to put validations in.
Kinda overpowered techinque. None of the other coders on the project could understand it at all. The whole stack got ripped out.