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

浪尽此生 提交于 2019-11-30 11:39:43

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 crummudgeon) 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 constness 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 nonconst-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();
}

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.

Björn Pollex

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.

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 ofconst_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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!