繁体   English   中英

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

[英]How to call a non-const method from a const method?

我的类中有一个 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方法内的某些内部状态,您还可以声明受影响的状态mutable

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

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

此外,您可能想阅读此答案以了解如何使用 RAII 使此临时状态更改异常安全。

const正确性的挑战之一是你不能半途而废。 要么全有,要么全无。 如果你尝试半途而废,你最终会陷入困境,就像你在这里一样。 你最终会得到一个不错的const -correct 类,它被一些疯狂的旧的、典型的遗留(或由一个旧的脾气暴躁的人编写)代码使用,这些代码不是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);类的操作来摆脱constSomeClass* 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();
}

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

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

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

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

 mutable QColor m_color;

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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