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

问题描述 投票:14回答:4

我在类中有一个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;
}
c++ methods const const-correctness
4个回答
9
投票

进行const正确性的挑战之一是您不能做到一半。要么全部要么一无所有。如果您尝试半途而废,那么您将陷入困境,就像在这里一样。最后,您会得到一个不错的const正确的类,该类被const正确的并且不起作用的一些疯狂的旧的(通常是旧的)遗留代码(或由旧的curmudgeon编写)使用。您只是想知道const-正确性是否值得所有麻烦。

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

您不能-不直接。你也不应该但是,还有另一种选择...

显然,您不能从const方法中调用非const方法。否则,const应用于成员函数时将没有任何意义。

const成员函数可以更改标记为mutable的成员变量,但是您已经表明,这无法实现。

[您可以尝试通过类似const的方式来消除SomeClass* me = const_cast<SomeClass*>(this);的正确性,但是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();
}

15
投票

您可以在const_cast指针上使用this

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


7
投票

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

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

这适用于您拥有类互斥对象之类的东西的情况。获取和释放互斥锁不会影响客户端可见的状态,但是从技术上讲,在const方法中禁止这样做。解决方法是标记互斥锁mutable。您的情况看起来很相似,尽管我认为您的班级需要进行一些重构才能使此解决方案适用。

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


7
投票

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

您不应该。如果使用this放弃const_cast的恒定性,则可能会遇到不确定的行为。 const_cast的使用将使编译器无法正常工作,但这不是解决方案。如果需要这样做,则意味着const函数不应该放在首位const。将其设为非常量。

或者,您应该执行其他操作,这将不需要您从const函数中调用非const函数。就像,不调用setColor函数吗?例如,将const函数拆分为多个函数(如果可以的话)?或者是其他东西?

在您的特定情况下,如果setColor仅设置某个成员变量,例如m_color,则可以将其声明为mutable

 mutable QColor m_color;

然后在您的const函数中进行设置,而无需调用setColor函数,也无需进行const_cast

© www.soinside.com 2019 - 2024. All rights reserved.