问题
I've got a const method in my class, which cannot be changed to non-const. In this method, I need to call a non-const method but the compiler doesn't let me do that.
Is there any way around it? Here is a simplified sample of my code:
int SomeClass::someMethod() const {
QColor saveColor = color();
setColor(QColor(255,255,255)); // Calling non-const method
// ....
setColor(saveColor); // restore color
return 1;
}
回答1:
One of the challenges of doing const
-correctness is you can't do it halfway. It's either all or nothing. If you try to do it halfway, you end up in a tough spot like you are here. You end up with a nice const
-correct class being used by some crazy old, typically legacy (or written by an old crummudgeon) code that isn't const
-correct and it just doesn't work. You're left wondering if const
-correctness is worth all the trouble.
I need to call a non-const method [from a const method]
You can't -- not directly. Nor should you. However, there is an alternative...
Obviously you can't call a non-const
method from a const
method. Otherwise, const
would have no meaning when applied to member functions.
A const
member function can change member variables marked mutable
, but you've indicated that this is not possible in your case.
You could attempt to cast away const
ness by doing something like SomeClass* me = const_cast<SomeClass*>(this);
but A) This will typically result in UB, or 2) It violates the whole idea of const
-correctness.
One thing you could do, if what you're really trying to accomplish would support this, is to create a non-const
proxy object, and do nonconst
-y stuff with that. To wit:
#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:
You could use const_cast
on this
pointer,
int SomeClass::someMethod() const {
const_cast<SomeClass*>( this )->setColor(...);// Calling non-const method
//whatever
}
but if you do that for an object that was originally declared const
you run into undefined behavior.
So this:
SomeClass object;
object.someMethod();
is okay, but this:
const SomeClass object;
object.someMethod();
yields undefined behavior.
The real solution is that your const
function should not be const
in the first place.
回答3:
If you require to change some internal state inside a const
-method you can also declare the affected state mutable
:
class Foo {
public:
void doStuff() const { bar = 5; }
private:
mutable int bar;
};
This is intended for cases where you have stuff like mutexes as members of your class. Acquiring and releasing a mutex does not affect client-visible state, but is technically forbidden in a const
-method. The solution is to mark the mutex mutable
. Your case looks similar, although I think your class requires some refactoring for this solution to be applicable.
Also, you might want to read this answer to see how you can make this temporary state-change exception-safe using RAII.
回答4:
How to call a non-const method from a const method?
You should not. You might run into undefined behaviour if you cast away the const-ness of this
, using const_cast
. The usage ofconst_cast
will shut the compiler's mouth up, but that isn't a solution. If you need to do, then it means the const function should not be const
in the first place. Make it non-const.
Or, you should do something else, which would not require you to call non-const function from const
function. Like, don't call setColor
function? Like, split the const function into more than one functions (if you can do that)? Or something else?
In your particular case, if setColor
only sets some member variable, say m_color
, then you can declare it mutable
:
mutable QColor m_color;
and then set it in your const function, without calling setColor
function, and without doing const_cast
.
来源:https://stackoverflow.com/questions/8325400/how-to-call-a-non-const-method-from-a-const-method