I was wondering about good practices in C++, and I was facing the problem of making a getter/setter for a class member.
So, why don't simply return the member by reference so this way I can modify or access its value to read it? Specifically, this is my code:
class Chest : public GameObject
{
public:
Chest();
~Chest();
static int& num_chests();
private:
static int num_chests_;
};
Is this a bad practice? Should I use these instead?
class Chest : public GameObject
{
public:
Chest();
~Chest();
static int num_chests();
static void set_num_chests(int num_chests);
private:
static int num_chests_;
};
So the rule of thumb is: Do not return a reference of the original object in the getter method. Instead, it should return a copy of the original object.
The reference-getter A reference-getter is a method that directly returns the reference to an attribute to access and edit it.
For each instance variable, a getter method returns its value while a setter method sets or updates its value. Given this, getters and setters are also known as accessors and mutators, respectively. The getter method returns the value of the attribute.
Unless you feel very strongly against it, use getter and setter member functions.
The reason int& num_chests()
or a public field is bad is that you are coupling client code that uses the num_chests
value to the fact that it is actually a field (an internal implementation detail).
Suppose that later you decided you would have a std::vector<Chest> chests
private field in your class. Then you wouldn't want to have a int num_chests
field -- it's horribly redundant. You would want to have int num_chests() { return chests.size(); }
.
If you were using a public field, now all of your client code needs to use this function instead of the previous field access -- every usage of the num_chests
value needs to be updated, because the interface has changed.
If you were using a function that returns a reference, you now have a problem because chests.size()
is a return by value -- you can't in-turn return that by reference.
Always encapsulate your data. It requires only a minimal amount of boilerplate code.
In response to comments saying you should just use public fields:
Keep in mind that the only benefit of using public fields (other than the remote possibility of some micro-optimization) is that you don't have to write the boilerplate code. "My teacher used to hate when I used public fields (and he was sooo annoying)" is a very poor argument for using public fields.
The purpose of your interface is not to be the simplest to program, but the simplest to use and extend.
If you fail to provide setter and getter methods, you are setting yourself up for later headaches. For example:
num_chests
?num_chests
cannot be negative?As you can see, an interface that is transparent to the user is also simpler to protect against user errors, and also extend in the future; this advantage comes at very little (if any) extra cost.
On the other hand, sometimes you do want to return a reference or pointer to an internal member. For example, the container classes in the Standard Library often offer a data()
method that retrieves a pointer to the underlying container (both in the const
and non-const
variations).
So, it is not a hard rule, but I would say that returning non-const references to private members defeats the purpose of OO programming.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With