如何从const方法调用非const方法

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

本文关键字:方法 const 调用      更新时间:2023-10-16

我的类中有一个const方法,它不能更改为非const。在这个方法中,我需要调用一个非const方法,但是编译器不允许我这样做。

有别的办法吗?下面是我的代码的一个简化示例:

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

可以在this指针上使用const_cast

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

但是如果你对一个最初声明为const的对象这样做,你会遇到未定义的行为。

:

SomeClass object;
object.someMethod();

是可以的,但是这个:

const SomeClass object;
object.someMethod();

产生未定义的行为。

真正的解决方案是您的const函数首先不应该是const

const -正确性的挑战之一是你不能半途而废。要么全有,要么全无。如果你半途而废,你就会像现在这样陷入困境。你最终会得到一个很好的const正确的类被一些疯狂的旧的,通常是遗留的(或由一个老脾气写的)代码所使用,这些代码不是const正确的,它只是不起作用。你会怀疑const的正确性是否值得这么多麻烦。

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

你不能——不能直接。你也不应该。然而,还有另一种选择…

显然你不能从const方法中调用非const方法。否则,const在应用于成员函数时就没有意义了。

const成员函数可以更改标记为mutable的成员变量,但是您已经指出在您的情况下这是不可能的。

你可以尝试通过做一些类似SomeClass* me = const_cast<SomeClass*>(this);的事情来抛弃const,但是A)这通常会导致UB,或者2)它违背了const的正确性。

你可以做的一件事,如果你真的试图完成将支持这一点,是创建一个非const代理对象,并做非const -y的东西用它。即:

#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();
}

如果您需要更改const -方法中的一些内部状态,您也可以声明受影响的状态mutable:

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

这适用于有互斥体之类的东西作为类成员的情况。获取和释放互斥锁不会影响客户端可见状态,但在const方法中技术上是禁止的。解决方案是将互斥标记为mutable。您的情况看起来类似,尽管我认为您的类需要一些重构才能适用此解决方案。

另外,您可能希望阅读此回答,了解如何使用RAII使此临时状态更改异常安全。

如何从const方法调用非const方法?

你不应该。如果使用const_cast抛弃this的const-ness,可能会遇到未定义的行为。使用const_cast会堵住编译器的嘴,但这不是解决方案。如果您需要这样做,那么这意味着const函数首先不应该是const。设置为非const

或者,您应该做其他事情,这将不需要您从const函数调用非const函数。比如,不要调用setColor函数?比如,将const函数拆分为多个函数(如果可以的话)?还是别的什么?

在您的特殊情况下,如果setColor只设置了某个成员变量,例如m_color,那么您可以将其声明为mutable:

 mutable QColor m_color;

,然后在const函数中设置它,不调用setColor函数,也不执行const_cast