我在类中有一个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;
}
进行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();
}
您可以在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
。
如果需要更改const
方法内部的某些内部状态,也可以声明受影响的状态mutable
:
class Foo {
public:
void doStuff() const { bar = 5; }
private:
mutable int bar;
};
这适用于您拥有类互斥对象之类的东西的情况。获取和释放互斥锁不会影响客户端可见的状态,但是从技术上讲,在const
方法中禁止这样做。解决方法是标记互斥锁mutable
。您的情况看起来很相似,尽管我认为您的班级需要进行一些重构才能使此解决方案适用。
此外,您可能希望阅读this answer,以了解如何使用RAII使此临时状态更改异常安全。
如何从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
。