C++ – Const and non-const methods, and possible mutable data member

cconstfunctions

I'm working on a design and implementation change due to a bug. The bug fix requires us to modify a class object in a const method. I think the two options are:

  1. Have the non-const method cast this to const (and hence call the const method)?
  2. Have the const method cast away const-ness (and hence call the non-const method)?

In the case of (1), we have to declare the data members as mutable.

In the case of (2), we can do away with mutable data members.

The third option – don't get into this situation in the first place – is no longer available.

What is the best practice for a const method and non-const method that operates on member data? Or, put another way, how should this design and implementation change proceed?


The gyrations are due to a bug fix and our extreme desire that "things just work" with existing code. We don't want to force users to rewrite their code, so we do something lazily in a const method (users call Foo and have never called Bar until the fix):

void Foo() const
{
    // Added due to bug fix
    if(!m_bar)
        Bar();
}

void Bar() const
{
    // m_1 and m_2 are mutable
    m_1 = ...
    m_2 = ...

    // m_3 and m_4 are untouched...

    m_bar = true;
}

The problem actually goes deeper into the design. For example, Bar is declared virtual and non-const in a base class. So we have to do these things while avoiding name hiding.


A similar question that takes some of the mutable approach: Is it a bad idea to use mutable for pre-allocated temporaries?

Best Answer

There are always two sides to constness: Being const in the sense of the programming language, and being logically constant. Say a C++ object has a pointer to a std::string object. If the C++ object is const, I can't change the pointer to point to a different std::string object. However, I can change the contents of the std::string object. Which doesn't change the object in the view of the language, but it logically changes the object.

const methods shouldn't logically change the object. Using "mutable", they can change the object. If you have for example a cache object, it is logically unchanged if it gives the same replies to the same requests. Whether it loads some object from disk to memory or unloads it from memory doesn't change how it reacts to requests.

Things like caching, on demand calculation, changing an internal representation, don't logically change the object, so I'd be Ok with making things mutable and changing them in a const method.

Related Topic