Search code examples
c++constantsfunction-qualifier

Const Member Function


The const member function guarantees that no member variables can be changed by the member function unless they are marked as mutable.

That being said it guarantees nothing else?

Here is a real example. I have a classes EventHandler and EventDispatcher.

class EventHandler
{
public:
   void registerHandler(EventHandler* handler) const   // Should this be a const?
   {
      EventDispatcher::registerHandler(handler);
   }
};

EventDispatcher   // Singleton Class
{
public:
   void registerHandler(EventHandler* handler)
   {
      mListeners.push_back(handler);
   }

private:
   std::vector<EventHandler*> mListeners;
};

Should EventDispatcher's registerHandler(EventHandler*) be const? It does not change its member variables, but it does change global state.


Solution

  • Correct, it makes no guarantees about any other state than the object itself. And I would say that there's no particular requirement that it doesn't modify global state. [If you take it to extremes, any function call does modify the current state of the processor - even if it's just storing the return address on the stack [1]].

    But a more reasonable thing would be that a const member function like this:

     class myclass
     {
     private:
        std::vector<int> v;
     public:
        std::vector<int> getV() const { return v; }
     };
    

    This will create a copy of the vector v - which in turn allocates memory (thus changing global state). An output function that feeds your object to a output stream would be a similar thing.

    If a member function modifies some global state (in a way that isn't obvious), then it probably should be made clear in the description of the function (documentation is useful sometimes).

    [1] Of course, the C++ and C standards do not state that the processor has to have a stack, return addresses, etc - the compiler could inline all the code, and not make any "calls" at all, or use magic to "remember" where to get back to - as long as the magic actually works, it's fine to rely on that.

    Edit based on your edited question:

    It's one of those that isn't entirely obvious in either direction, you would expect the registerHanlder to do something like "store the handler object somewhere". But since it's not modifiying the object itself, it may help to explain that it's updating the dispatcher class. Of course, if it's not actually updating the class itself, or using anything from the class, you probably should make it static rather than const - that way it's clear that it's not actually modifying the object itself.

    Aside: As it is written, your code won't work, since EventDispatcher::registerHandler is not a static member, and your EventHandler::registerHandler is not referring to an instance of EventDispatcher. You would either have to make an instance of EventDispatcher as a global variable, or make EventDispatcher::registerHandler a static function and make mListeners a static member. Or something else along those lines.