Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using setters in constructor

I'm a Java developer trying to pick up C++. Is it okay to use a setter inside a constructor in order to reuse the sanity checks the setter provides?

For example:

#include <stdexcept>
using namespace std;

class Test {
    private:
        int foo;
        void setFoo(int foo) {
            if (foo < 42) {
                throw invalid_argument{"Foo < 42."};
            }

            this->foo = foo;
        }

    public:
        Test(int foo) {
            setFoo(foo);
        };
};
like image 233
Meme Master Avatar asked Jul 13 '16 08:07

Meme Master


People also ask

Should you use setters in constructor?

You should not call getters and setters from the constructor. A constructor constructs the specific class in which it is defined. It is its job to initialise the fields because - well - nothing else will. The only way to guarantee initialising the fields is to assign them.

Can we use setter in constructor in Java?

Avoiding setters in constructors makes it clear that the only thing the constructor is doing is setting the instance variable and skipping any other behavior that happens in the setter. Save this answer.

Should getters and setters be before or after constructor?

Getters and setters are used after you have initialized your class members using the constructor. Getters are used to acquire class member values from the instance of the class by classes/functions located outside the class. Setters are used to alter the value of the corresponding class member in the same manner.

Can we use getter and setter in constructor in C++?

No, they have different purposes. A constructor is used to initialise an object (eg, set values for its attributes), while getters and setters are used to encapsulate data and control its modification rules. An example may help.


3 Answers

Yes, it is recommended to do this, basically for the reason you already mentioned.

On the other hand you should ask yourself if you need the setter at all and not directly implement the checks inside the constructor. The reason I am writing this is that setters in general result in mutable state which has many disadvantages as opposed to immutable classes. However sometimes they are required.

Another recommendation: If your class variable is an object and you can modify the constructor of this object, you could put the check into the constructor of this object:

class MyFoo {
public:
    MyFoo(int value) {
        if (value < 42) {
            throw invalid_argument{"Foo < 42."};
        }
        v = value;
    }
private:
    int v;
}

This will enable you to use an initialization list in the constructor of your Test class:

Test(int foo) : foo(foo) {}

However, now the check is a property of the class of the variable and no longer one of the owning class.

like image 103
Frank Puffer Avatar answered Sep 17 '22 14:09

Frank Puffer


Yes you can. It's fine as long as your setters are not virtual, because it's inheritance hierarchy in calling right functions as the "this" ptr is not ready yet.

Here is Herb Sutter GOTW on this matter: http://www.gotw.ca/gotw/066.htm

like image 42
paweldac Avatar answered Sep 18 '22 14:09

paweldac


Yes, that's fine as long as it makes sense to have a setter for a particular member variable (have some logic that can't be checked by assignment only for example) . In this example, setFoo could've just taken an unsigned int and the caller would know not to pass negative values. Which in turn could eliminate the check and thus the need for a setter. For more elaborate checks, a setter and usage of that setter in the constructor is just fine.

like image 34
Hatted Rooster Avatar answered Sep 18 '22 14:09

Hatted Rooster