简体   繁体   中英

How to call a non-const method from a const method?

I've got a const method in my class, which cannot be changed to non-const. In this method, I need to call a non-const method but the compiler doesn't let me do that.

Is there any way around it? Here is a simplified sample of my code:

int SomeClass::someMethod() const {
    QColor saveColor = color();
    setColor(QColor(255,255,255)); // Calling non-const method

    // ....

    setColor(saveColor); // restore color

    return 1;
}

You could use const_cast on this pointer,

int SomeClass::someMethod() const {
    const_cast<SomeClass*>( this )->setColor(...);// Calling non-const method
    //whatever
}

but if you do that for an object that was originally declared const you run into undefined behavior.

So this:

SomeClass object;
object.someMethod();

is okay, but this:

const SomeClass object;
object.someMethod();

yields undefined behavior.

The real solution is that your const function should not be const in the first place.

If you require to change some internal state inside a const -method you can also declare the affected state mutable :

class Foo {
public:
    void doStuff() const { bar = 5; }
private:
    mutable int bar;
};

This is intended for cases where you have stuff like mutexes as members of your class. Acquiring and releasing a mutex does not affect client-visible state, but is technically forbidden in a const -method. The solution is to mark the mutex mutable . Your case looks similar, although I think your class requires some refactoring for this solution to be applicable.

Also, you might want to read this answer to see how you can make this temporary state-change exception-safe using RAII.

One of the challenges of doing const -correctness is you can't do it halfway. It's either all or nothing. If you try to do it halfway, you end up in a tough spot like you are here. You end up with a nice const -correct class being used by some crazy old, typically legacy (or written by an old curmudgeon) code that isn't const -correct and it just doesn't work. You're left wondering if const -correctness is worth all the trouble.

I need to call a non-const method [from a const method]

You can't -- not directly. Nor should you. However, there is an alternative...

Obviously you can't call a non- const method from a const method. Otherwise, const would have no meaning when applied to member functions.

A const member function can change member variables marked mutable , but you've indicated that this is not possible in your case.

You could attempt to cast away const ness by doing something like SomeClass* me = const_cast<SomeClass*>(this); but A) This will typically result in UB, or 2) It violates the whole idea of const -correctness.

One thing you could do, if what you're really trying to accomplish would support this, is to create a non- const proxy object, and do non const -y stuff with that. To wit:

#include <iostream>
#include <string>
using namespace std;

class Gizmo
{
public:
    Gizmo() : n_(42) {};
    void Foo() const;
    void Bar() { cout << "Bar() : " << n_ << "\n"; }
    void SetN(int n) { n_ = n; };
    int GetN() const { return n_; }
private:
    int n_;
};

void Gizmo::Foo() const
{
    // we want to do non-const'y things, so create a proxy...
    Gizmo proxy(*this);
    int save_n = proxy.GetN();
    proxy.SetN(save_n + 1);
    proxy.Bar();
    proxy.SetN(save_n);
}

int main()
{
    Gizmo gizmo;
    gizmo.Foo();
}

How to call a non-const method from a const method?

You should not. You might run into undefined behaviour if you cast away the const-ness of this , using const_cast . The usage of const_cast will shut the compiler's mouth up, but that isn't a solution. If you need to do, then it means the const function should not be const in the first place. Make it non-const.

Or, you should do something else, which would not require you to call non-const function from const function. Like, don't call setColor function? Like, split the const function into more than one functions (if you can do that)? Or something else?

In your particular case, if setColor only sets some member variable, say m_color , then you can declare it mutable :

 mutable QColor m_color;

and then set it in your const function, without calling setColor function, and without doing const_cast .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM