How to call a non-const method from a const method? - c++

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;
}

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.

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 curmudgeon) 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 constness 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();
}

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.

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.

Related

How to deal with constness when the method result is cached?

I have a class with a method (getter) that performs some relatively expensive operation, so I want to cache its result. Calling the method does not change behavior of the object, but it needs to store its result in this, so it can't be const.
The problem is that I now have another method that is const and I need to invoke my getter. Is there some generally accepted solution to this problem? Should I bypass the constness checking in the getter to make it const, (Coudn't that cause problems with optimizing compiler?) or I have to propagate the non-constness to all methods that use this getter?
Example:
class MyClass
{
public:
Foo &expensiveGetter() /*const?*/
{
if (cachedValue == nullptr) {
cachedValue = computeTheValue();
}
return *cachedValue;
}
void myMethod() /* How to make this const? */
{
auto &foo = expensiveGetter();
// etc.
}
private:
Foo *cachedValue = nullptr;
}
I am looking for something like the RefCell in Rust.
This is one of the situations the mutable specifier fits particularly well. When a class member is mutable, that member can be changed even if the enclosing class is const.
So, if MyClass::cachedValue is a mutable Foo* instead of a Foo*, you can have const member functions in MyClass that make changes to cachedValue and then all calling code can just act on a const MyClass as normal.

Can I delete function for an rvalue version of object?

For legacy reasons, there's a lot of usage of const char* in the code I'm working on. I am trying to limit that, and stumbled on something I'd like to know. I have something like:
class AClass {
public:
const char* getValue() { return _value.c_str(); }
private:
std::string _value;
}
But this class now may be returned by copy, eg. by function:
AClass getAClass();
We also might wanna pass that to something like this:
void functionFromOtherLibrary(const char* value);
Now thinking about that, this might cause an error:
functionFromOtherLibrary(getAClass().getValue());
since the intermediate is eligible to be destroyed at that point. Even if the above goes OK, because it's one statement, this probably won't:
const char* str = getAClass().getValue();
functionFromOtherLibrary(str);
So I was thinking of writing something like:
class AClass {
public:
const char* getValue() { return _value.c_str(); }
const char* getValue() && = delete;
}
to forbid calls for that method on rvalues. Just trying that gave me:
error C2560: cannot overload a member function with ref-qualifier with a member function without ref-qualifier
I'm not sure if this:
is valid construct and
is ever necessary. I've seen a lot of code that returns const char*s and it always seems to rely on the fact that the object returning the value will still exist and hold the source std::string.
I would really appreciate a more detailed explanation what happens when code uses std::strings to hold strings but only communicates with C strings.
And if you want to suggest removing C strings - that's what I'm trying to do right now. I still want an answer though.
You can't overload a function with a ref-qualifier with a function without a ref-qualifier. The MSVC error text is nice and clear on this point.
But you can just add the ref-qualifier to the other one:
class AClass {
public:
const char* getValue() & { return _value.c_str(); }
const char* getValue() && = delete;
};
Whether this is the right design or not is a separate question - but if you decide that it is, this is how you would do it.

Cast const member function to non-const

Is casting the constness of member function pointers defined in C++? Is the following valid code?
struct T {
void foo(int i) const { std::cout << i << std::endl;};
};
void (T::*f1)(int) const = &T::foo;
void (T::*f2)(int) = reinterpret_cast<void (T::*)(int)>(f1);
T t;
(t.*f2)(1);
Update:
The reason why I need this is that I'm writing a function that accepts both an object and a member function pointer to that object. I need a version for const objects (accepting only const functions) and a normal one. Since I don't want duplicate code, my idea was to put the actual code in the non-const version and call it from the const one, casting away any consts.
Compiler eats it.
But the backward cast is more useful.
And again but - it is better to don't use it, const_cast is usually just a quick and dirty solution, which you apply only when there are not any other solution.
Answer to update
If I understand you correctly you are going to use one object and two function. First function accepts const object and const member-function, second - non-const object and non-const member-function.
According to given information you can change second function to accept non-const object and const member-function. And give them one non-const object and its const member-function.
Yes, it is defined, but you maybe don't want it if the function is really const, because some compiler optimizations (namely return value caching) depend on the function being const.
You can do it, but it has no meaning, wherever you can call f2, you can also call f1 too. You should cast in the other way. But if something, you should cast the object, not the function.
void (T::*f1)(int) const = &T::foo;
void (T::*f2)(int) = reinterpret_cast<void (T::*)(int)>(f1);
T t;
(t.*f2)(1); // compiles
(t.*f1)(1); // this compiles too!!
but if you have
const T t;
(t.*f2)(1); // error t is const
(t.*f1)(1); // still compiles
The only was to resolve the ambiguity is to perform a static_cast, this is basically a language feature
#include <boost/typeof/typeof.hpp>
struct Test
{
const int& foo();
const int& foo() const;
};
int main()
{
typedef const int&(Test::*non_const_ptr)();
typedef const int&(Test::*const_ptr)()const;
BOOST_TYPEOF(static_cast<non_const_ptr>(&Test::foo)) ss;
}
I don't see a reason for doing this: even if you could, you'd make it more restrictive.
Let's say you have a class Foo:
class Foo {
void f() const;
void g();
}
And some snippet of code:
Foo a;
const Foo b;
Then you can call both a.f() and a.g(), but not b.g() because b is const. As you can see, placing const after a member function makes it less restrictive, not more.
And, by reinterpret_casting this pointer, you'll get the pointer with exact same value(due to the nature of reinterpret_cast), and if you try to call it, you'll get into the same T::foo()

C++ Singleton class returning const reference

I have an a class which is singleton as defined follows
class myData {
private:
myData (void); // singleton class.
// Copy and assignment is prohibted.
myData (const myData &);
myData & operator=(const myData &);
static myData* s_pInstance;
public:
~myData (void);
static const myData & Instance();
static void Terminate();
void myFunc() { cout << "my function..." ;}
};
// In cpp file.
myData* myData::s_pInstance(NULL);
myData::myData(){}
myData::~myData()
{
s_pInstance = NULL;
}
const myData& myData::Instance()
{
if (s_pInstance == NULL)
{
s_pInstance = new myData();
}
return *(s_pInstance); // want to avoid pointer as user may deallocate it, so i used const referense
}
void main() {
(myData::Instance()).myFunc();
}
I am getting following error
error C2662: 'myData::myFunc' : cannot convert 'this' pointer from 'const myData' to 'myData&'
how to avoid above problem and call a function from Instance function which is returning const reference?
Thanks!
You'd want to declare func() as a constant member function, so the compiler knows it won't violate the const'd return value from the instance() function.
You could instead also make the instance() function return a 'regular' reference as apposed to a const one.
So either turn:
void myFunc() into void myFunc() const
Or turn:
const myData& myData::Instance() into myData& myData::Instance()
If you are calling a function on a const reference, the function you call must also be const, in your case void myFunc() const.
Otherwise you might return a non-const reference, if that works better.
The error says that myData::Instance() is a const instance of the class, and it can't call myFunc() on that, because myFunc() might change the instance, and you can't change a const instance.
Of course, you know that myFunc() can't really change the instance, but you must advertise this fact, as follows:
void myFunc() const { cout << "my function..." ;}
Avoiding the whole discussion of whether Singleton is a good to have pattern or the source of all evil, if you are actually implementing a singleton, chances are that const correctness will not work there as you expect it, so you should be aware of some pitfalls.
First your error: your Instance() static member returns a const reference, and that means that you can only perform operations that do not modify the object, i.e. call member functions marked as const, or use public members if present in a way that do not modify their values. My suggested solution is modify Instance() to return a non-const reference, rather than making func() const as others suggest.
Now for a longer explanation to the problem of const-correctness in general when applied to your particular Singleton problem. The basic problem is that when you implement a type, you divide those members that modify the object from those that don't, and you mark the latter as const member functions so that the compiler knows of your promise (allows you to call that method on a constant object) and helps you not break it (complains if you try to modify the state in the definition of the method). A method that is marked as const can be applied to both a constant and non constant object, but a method that is not marked const can only be applied to an object that is not const.
Back to the original piece of code, if you implement a singleton and the only way of accessing the object is by an Instance() method that returns a const reference, you are basically limiting all user code to use only const methods implemented in your interface. That means that effectively either all methods are non-mutating, or they are useless (const_cast should never be used). That in turn means that if you have any non-const operation you want to provide an Instance() method that returns a non-const reference.
You could consider implementing two variants of Instance(), but that will not be really helpful. Overload resolution will not help in user code to determine which version to use, so you will end up having to different methods: Instance(), ConstInstance() (choose your names), which means that it is up to user code to determine which one to use. The small advantage is that in their code, the choice of accessor will help documenting their intended usage, and maybe even catch some errors, but more often than not they will just call the non-const version because it works.

Using 'const' in class's functions [duplicate]

This question already has answers here:
Meaning of 'const' last in a function declaration of a class?
(12 answers)
Closed 5 years ago.
I've seen a lot of uses of the const keyword put after functions in classes, so i wanted to know what was it about. I read up smth at here: http://duramecho.com/ComputerInformation/WhyHowCppConst.html .
It says that const is used because the function "can attempt to alter any member variables in the object" . If this is true, then should it be used everywhere, because i don't want ANY of the member variables to be altered or changed in any way.
class Class2
{ void Method1() const;
int MemberVariable1;}
So, what is the real definition and use of const ?
A const method can be called on a const object:
class CL2
{
public:
void const_method() const;
void method();
private:
int x;
};
const CL2 co;
CL2 o;
co.const_method(); // legal
co.method(); // illegal, can't call regular method on const object
o.const_method(); // legal, can call const method on a regulard object
o.method(); // legal
Furthermore, it also tells the compiler that the const method should not be changing the state of the object and will catch those problems:
void CL2::const_method() const
{
x = 3; // illegal, can't modify a member in a const object
}
There is an exception to the above rule by using the mutable modifier, but you should first get good at const correctness before you venture into that territory.
Others have answered the technical side of your question about const member functions, but there is a bigger picture here -- and that is the idea of const correctness.
Long story short, const correctness is about clarifying and enforcing the semantics of your code. Take a simple example. Look at this function declaration:
bool DoTheThing(char* message);
Suppose someone else wrote this function and you need to call it. Do you know what DoTheThing() does to your char buffer? Maybe it just logs the message to a file, or maybe it changes the string. You can't tell what the semantics of the call are by just looking at the function declaration. If the function doesn't modify the string, then the declaration is const incorrect.
There's practical value to making your functions const correct, too. Namely, depending on the context of the call, you might not be able to call const-incorrect functions without some trickery. For example, assume that you know that DoTheThing() doesn't modify the contents of the string passed to it, and you have this code:
void MyFunction()
{
std::string msg = "Hello, const correctness";
DoTheThing(msg.c_str());
}
The above code won't compile because msg.c_str() returns a const char*. In order to get this code to compile, you would have to do something like this:
void MyFunction()
{
std::string msg = "Hello, const correctness";
DoTheThing(msg.begin());
}
...or even worse:
void MyFunction()
{
std::string msg = "Hello, const correctness";
DoTheThing(const_cast<char*>(msg.c_str()));
}
neither of which, arguably, are 'better' than the original code. But because DoTheThing() was written in a const-incorrect way, you have to bend your code around it.
The meaning is that you guarantee to clients calling a const function member that the state of the object will not change. So when you say a member function is const it means that you do not change any of the objects member variables during the function call.
const, when attached to a non-static class method, tells the compiler that your function doesn't modify the internal state of the object.
This is useful in two ways:
If you do write code that changes internal state in your const method, the compiler catches the error, moving a programming error from run-time to compile-time.
If client code calls a non-const method on a constant pointer, the compiler catches the error, ensuring the "chain of not changing things" is maintained.
Typically you want to declare all non-mutating non-static class methods as const. This allows calling code to use the const qualifier on pointers, and it helps catch mistakes.
Typical C++: you can declare a class member variable "mutable" and then change it even from a const method.
The const keyword used after a method indicate that this method doesn't modify the object on which it's called. This way, this method can be called on a const version of the object.
If this is true, then should it be used everywhere, because i don't want ANY of the member variables to be altered or changed in any way?
Well, no. Sometimes you do want instance methods to modify members. For example, any set method will obviously need to set variables, so it's not the case that you should put const everywhere. But if your object's state is totally immutable, first consider whether it might not be better to have no instances at all (i.e., a static class), and if that's not the case, then make everything const.
It's quite unusual not to want to have any member variables changed, but if that's what your class requires, then you should make all your member functions const.
However, you probably do want to change at least some members:
class A {
private:
int val;
public:
A() : val(0) {}
void Inc() { val++; }
int GetVal() const { return val; };
};
Now if I create two instances of A:
A a1;
const A a2;
I can say:
a1.GetVal();
a2.GetVal();
but I can only say:
a1.Inc();
trying to change the value of a constant object:
a2.Inc();
gives a compilation error.