Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: What's wrong with const public members?

Tags:

c++

I am reading some code where a class has private const data members, and then a whole bunch of public methods that provide read-only access to those data members.

What is the point of this? Why not just make those private data members public? They are const, so the access is by definition read-only, and people can access them via theClass.theMember rather than theClass.getTheMember(), which is easier, plus you avoid having to create all those public methods in the first place. One for each member variable, meaning that's O(n) inefficiency!

like image 392
Make Avatar asked Oct 17 '18 12:10

Make


2 Answers

Unless the accessor methods actually do something other than providing a reference, they are indeed superfluous.

This something can be, for instance:

  • Setter: Checking that the given value is actually valid.

  • Getter: Derive the requested value on the fly from something else.

  • Setter: Ensure that the given value is consistent with other data members.

  • Setter: Notify some data consumer(s) of the change

  • ...

However, if you are writing stuff like

private:
    const int _foo;

public:
    const int& foo() const { return _foo; }

there is no advantage over writing

public:
    const int foo;

instead. You cannot do anything with the later that you can't do with the former.

Likewise, the code

private:
    int _foo;

public:
    int& foo() { return _foo; }
    const int& foo() const { return _foo; }

provides no benefit over

public:
    int foo;

because any user can set _foo to any value they like without the object even noticing it.


So, my advice would be:

  • Declare data members private by default.

  • If you need read-only access but the data member is mutable, provide a getter.

  • If the data member is const and readable, use public: const

  • If users are to be allowed to just supply any value at any time, go ahead and make the member public. That's just being honest: The class itself has no control over the member's value, whatsoever.

    Note that this also happens extremely infrequently. In the vast majority of cases, you want your class to provide some abstraction, which means that it's not just a bunch of public data members. A well-written class should implement some needed behavior, not just be a collection of data. Also, if the class where just a bunch of public data members, you would declare it as a struct, wouldn't you?

  • If you find that you need the class to do something when a public variable is accessed, turn it into a private one, provide the relevant accessors, and let your compiler point you to all the places in the code that need to be updated.

    This also happens very infrequently, but it will force you to actually look at all the uses of the data member before you change the behavior of its access. This may be a good thing as it gives you a chance to spot problems with the changed behavior before they show up in the tests and/or production. You won't be forced to revisit the calling sites if you already provided the vanilla accessors for the variable.

like image 50
cmaster - reinstate monica Avatar answered Sep 20 '22 12:09

cmaster - reinstate monica


As @PetarVelev point out it is style. For many people having setters and getters is a boiler plate code, but usually they forgot why this was invented.

And this was invented to make maintenance of code easy. Imagine some class with some properties. This property is used all over the project. Now requirement has changed and you have to do something every time property is accessed something must happen. For example when value is changed notification should be sent (setters should be updated). Or you have noticed that calculating some property is costly, so it has to be lazy evaluated (getter should be corrected).

When you write this property (class field) you didn't know that there will be such issues to solve. If you expose this as public field then to resolve this issue you have to spend hours to find every use of this value and correct it. On other hand if this is done by using setter and getter you will spend 5-10 minutes to fix it including adding a tests.

So having setters and getters is a good practice, where you will lose 10 seconds to write them as boiler plate code, but save lots of time if some radical change is needed. Good example is Qt freamework.

So if you are sure that requirement will not change there is no point to use getter setter, but if you have doubts it is better to use them.

Now in your case where constant filed is exposed by getter is a bit strange. I'm suspecting that this is some example of functional programing, but without seeing actual code is hard to tell.

like image 20
Marek R Avatar answered Sep 22 '22 12:09

Marek R