0

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.

user870130
  • 565
  • 1
  • 8
  • 16
  • Are you asking if it's "ok" to modify non-member/static variables within a `const` member function? ("ok" meaning doesn't break the "rules" of what a `const` member functions intentions are)?? – txtechhelp May 09 '14 at 23:11
  • There's no single objectively correct answer. However, as a practical matter any attempt to infuse C++'s low level language features with higher level semantics, always run into severe difficulties, with net negative utility. For C++ it *is* often necessary to use the language features in ways restricted by mere convention, in order to emulate higher level features (e.g., think about using the preprocessor to implement modules), but that does not identify individual language features with the higher level concepts. – Cheers and hth. - Alf May 09 '14 at 23:12
  • @txtechhelp Each time I write a member function and then add a const I go down this rabbit hole of wondering if this is the intended use. I think to myself, "Yes, my member function doesn't change any of its member functions, but it does call transmogrify() which then calls defrangulate(). Is this really const?" – user870130 May 09 '14 at 23:19
  • 1
    check this! http://stackoverflow.com/questions/751681/meaning-of-const-last-in-a-c-method-declaration –  May 09 '14 at 23:19

2 Answers2

3

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.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
2

What does the const keyword behind a method declaration guarantee?

The guaranty is a contractual reminder, rather than 'physical' memory barrier.

Thus, if you implement the const keyword correctly, the compiler will be able to help you to detect possible bugs.

However, no C/C++ compiler will stop you from modifying the member state directly; neither via fields nor by casting the object reference to a pointer and modifying the underlying memory.

Is my const method allowed to change (local/global) state?

A const method is not allowed to change the external behaviour of the system, but it is perfectly acceptable for a const method to change the internal state.

In other words, after calling all const methods randomly a couple of times, the system should still provide the same behaviour it did initially.

On the other hand, if the const method feels like caching a time consuming calculation and reuse it for the next call, it should be allowed. Same goes for a logger class that logs statistics, but does not change the behaviour of the system.

tofi9
  • 5,775
  • 4
  • 29
  • 50
  • I am not actually trying to access global variables. It was just a simple example. I think Mats Petersson's answer touches on my confusion when he mentioned global state. Another example, a const member function could potentially lock another class's resource. Changing the global state, but none of it's local member variables. – user870130 May 09 '14 at 23:33
  • @user870130 it's about the behaviour, rather than state. In object orientation, behaviour is all that matters. I've updated my answer. – tofi9 May 09 '14 at 23:37