我的类中有一个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;
}
答案 0 :(得分:14)
您可以在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
。
答案 1 :(得分:8)
做const
的挑战之一 - 正确性是你不能半途而废。无论是全有还是全无。如果你试图半途而废,那你就像在这里一样陷入困境。你得到了一个很好的const
- 正确的类被一些疯狂的旧的,通常是遗留的(或由旧的crummudgeon写的)代码使用,而不是const
- 正确而且它不起作用。你不知道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();
}
答案 2 :(得分: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
。
答案 3 :(得分:7)
如果您需要更改const
- 方法中的某些内部状态,您还可以声明受影响的状态mutable
:
class Foo {
public:
void doStuff() const { bar = 5; }
private:
mutable int bar;
};
这适用于您将类似互斥锁的内容作为班级成员的情况。获取和释放互斥锁不会影响客户端可见状态,但在const
- 方法中技术上是禁止的。解决方案是标记互斥锁mutable
。您的案例看起来很相似,但我认为您的课程需要进行一些重构才能使此解决方案适用。
此外,您可能希望阅读this answer以了解如何使用RAII使此临时状态更改异常安全。