In C++, I want my interface, .h to say int GetSomeInt() const;… but actually the method *DOES* update “this”.

0 votes
asked Nov 26, 2008 by corey-trager

I'm adding some lazy initialization logic to a const method, which makes the method in fact not const. Is there a way for me to do this without having to remove the "const" from the public interface?

int MyClass::GetSomeInt() const
{
    // lazy logic
    if (m_bFirstTime)
    {
        m_bFirstTime = false;
        Do something once
    }

    return some int...

}

EDIT: Does the "mutable" keyword play a role here?

5 Answers

0 votes
answered Nov 26, 2008 by e-james

set the m_bFirstTime member to be mutable

0 votes
answered Nov 26, 2008 by john-dibling

Make m_bFirstTime mutable:

class MyClass
{
  : :
  mutable bool m_bFirstTime;
};

...but this is also very often an indication of a design flaw. So beware.

0 votes
answered Nov 26, 2008 by john-dibling

Actually, you said that you didn't want to change the header file. So your only option is to cast away the constness of the this pointer...

int MyClass::GetSomeInt() const
{
    MyClass* that = const_cast<MyClass*>(this);

    // lazy logic
    if (that->m_bFirstTime)
    {
        that->m_bFirstTime = false;
        Do something once
    }

    return some int...

}

If using mutable raises a red flag, this launches a red flag store in to orbit. Doing stuff like this is usually a really bad idea.

0 votes
answered Nov 26, 2008 by eclipse

In any case - make note that this is no longer going to be thread safe. You can often rely on an object to be thread safe if it only has const methods (or you use only the const methods after initialization). But if those const methods are only logically const, then you lose that benefit (unless of course you start locking it all the time).

The only compiler optimization that could cause havok would be for the compiler to figure out that you're calling the method twice with the same arguments, and just reuse the first return value - which is fine as long as the function truly is logically const, and returns the same value for a given set of arguments (and object state). Even that optimization isn't valid if it's possible that anyone (including another thread) has had access to the object to call non-const methods on it.

mutable was added to the language specifically for this case. C++ is a pragmatic language, and is happy to allow corner cases like this to exist for when they are needed.

0 votes
answered Nov 26, 2008 by andrew-stein

I think of this problem as involving two concepts: (1) "logically const" and (2) "bitwise const". By this I mean that getting some int from a class, does not logically change the class and in most cases it does not change the bits of the class members. However, in some cases, like yours, it does.

In these cases, where the method is logically const but not bitwise const, the compiler cannot know this. This is the reason for the existence of the mutable keyword. Use it as John Dibling shows, but it is not a design flaw. On the contrary, there are many cases where this is necessary. In your example, I presume that the calculation of the int is expensive, so we do not want to calculate it if it is not needed. In other cases, you may wish to cache results of methods for later use, etc.

BTW, even though you have accepted the "mutable" answer as correct, you do have to update the .h!

Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...