Search code examples
c++mutable

C++ mutable appropriate in this case?


I would like to ask if the use of mutable is appropriate here:

#include <iostream>

class Base
{
protected:
  int x;

public:
  virtual void NoMod() const
  {
    std::cout << x << std::endl;
  }
  void Draw() const
  {
    this->NoMod();  
  }
};

class Derive : public Base
{
private:
  mutable int y;

public:
  void NoMod() const
  {
    y = 5;
  }
};

int main()
{
  Derive derive;

  // Test virtual with derive
  derive.Draw();

  return 0;
}

The Base class is a 3rd-party library. I'm extending it to provide my own NoMod(). The library original NoMod() is declared as a const.

My NoMod() differs from Base in the fact that it needs to modify its own member variable.

Thus, for my own NoMod() to compile and get called when Draw() is called, I had to

1) Implement Derive::NoMod() as a const
2) make my int y mutable.

Is this the best I can do?


Solution

  • As 'head geek' described, the answer to your question depends on how your data member is used.

    I distinguish two types of data members in a class.

    I use the common term 'attribute' to refer to data members that are the logical state or 'value' of the object. Typically attributes are rarely declared as mutable.

    I have coined the protologism 'contribute' it denote data members that are simply 'working memory/storage' and that are somewhat divorced from the state of the object. Contributes have no contextual relevance to the user of the object, they exist in the class only to contribute to the maintenance and efficient operation of the object. Contributes are usually declared in the class as mutable and are always private or protected.

    For example let's say your object is a linked list, so you have a pointer to the first item in the list. I would consider this pointer a contribute because it does not represent the data in the list. Even if the list is sorted and the pointer is set to the new first item in the list, the user of the list object could care less how the list is maintained. Only that the list data has been modified or not and that the the list is sorted or not is relevant to the user's perspective. Even if you had a booean data member 'sorted' to quickly determine if the list is in a sorted state, that too would be a contribute because it is the list structure itself which imbues the sorted state, the 'sorted' variable member is used simply to efficiently remember the state without having to scan the list.

    As another example, if you have a const method that searches the list. Suppose you know that typically the search will return the most recently previously searched for item, you would keep a pointer in your class to such a item so your method can first check if the last found item matches the search key before searching the entire list (if the method does indeed need to search the list and finds an item, the pointer would be updated). This pointer I would consider to be a contribute because it is only there to help speed up the search. Even though the search updates the pointer contribute, the method is effectively const because none of the items' data in the container are modified.

    So, data members that are attributes are usually not declared mutable, and data members that contribute to the functioning of an object will usually be mutable.