Search code examples
c++static-analysisconst-correctnessfunction-qualifier

Should I declare these member functions const?


I'm working on some C++ code where I have several manager objects with private methods such as

void NotifyFooUpdated();

which call the OnFooUpdated() method on the listeners of this object.

Note that they don't modify the state of this object, so they could technically be made const methods, even though they typically modify the state of the system as a whole. In particular, the listener objects might call back into this object and modify it.

Personally I'd like to leave them as they are and not declare them const.

However, our static code checker QAC flags this as a deviation, so I either have to declare them const, or I have to argue why they should stay non-const and get a grant for the deviation.

What are arguments for not declaring these methods const?
Or should I follow QAC and declare them const?
Should I adopt a strictly local viewpoint restricted to this object, or consider the system as a whole?


Solution

  • Loosely speaking you have a container class: A manager full of observers. In C and C++ you can have const containers with non-const values. Consider if you removed one layer of wrapping:

    list<Observer> someManager;
    
    void NotifyFooUpdated(const list<Observer>& manager) { ... }
    

    You would see nothing strange about a global NotifyFooUpdated taking a const list, since it does not modify the list. That const argument actually makes the argument parsing more permissive: The function accepts both const and non-const lists. All the const annotation on the class method version means is const *this.

    To address another perspective:

    If you can't guarantee that the object you invoked the function on remains the same before and after the function call, you should generally leave that as non-const.

    That's only reasonable if the caller has the only reference to the object. If the object is global (as it is in the original question) or in a threaded environment, the constness of any given call does not guarantee the state of the object is unchanged across the call. A function with no side-effects and which always returns the same value for the same inputs is pure. NotifyFooUpdate() is clearly not pure.