C++ const question - c++

If I do this:
// In header
class Foo {
void foo(bar*);
};
// In cpp
void Foo::foo(bar* const pBar) {
//Stuff
}
The compiler does not complain that the signatures for Foo::foo do not match. However if I had:
void foo(const bar*); //In header
void Foo::foo(bar*) {} //In cpp
The code will fail to compile.
What is going on?
I'm using gcc 4.1.x

In the first, you've promised the compiler, but not other users of the class that you will not edit the variable.
In your second example, you've promised other users of the class that you will not edit their variable, but failed to uphold that promise.
I should also note that there is a distinct difference between
bar* const variable
and
const bar* variable
and
const bar* const variable
In the first form, the pointer will never change, but you can edit the object that is pointed to. In the second form, you can edit the pointer(point it to another object), but never the variable that it points to. In the final form, you will neither edit the pointer, nor the object it points to. Reference
To add a bit more of a clarification to the question stated, you can always promise MORE const than less. Given a class:
class Foo {
void func1 (int x);
void func2 (int *x);
}
You can compile the following implementation:
Foo::func1(const int x) {}
Foo::func2(const int *x) {}
or:
Foo::func1(const int x) {}
Foo::func2(const int* const x) {}
without any problems. You've told your users that you may possibly edit their variables. In your implementation, you've told the compiler that this particular implementation will not edit those variables, even though the told the users you might. You haven't broken a promise to the user, and so the code compiles.

See this question, this question, and this question.
Basically, the const only means that the function will not modify the pointer's value. The pointers contents are not const, the same as the header's signature.

The const keyword in the first example is meaningless. You are saying that you don't plan on changing the pointer. However, the pointer was passed by value and so it dos not matter if you change it or not; it will not effect the caller. Similarly, you could also do this:
// In header
class Foo {
void foo( int b );
};
// In cpp
void Foo::foo( const int b ) {
//Stuff
}
You can even do this:
// In header
class Foo {
void foo( const int b );
};
// In cpp
void Foo::foo( int b ) {
//Stuff
}
Since the int is passed by value, the constness does not matter.
In the second example you are saying that your function takes a pointer to one type, but then implement it as taking a pointer to another type, therefore it fails.

So the second const in:
void Foo::foo(const bar* const);
Is not part of the method signature?

This is simpler to understand with a variable type other than a pointer. For example, you can have the following function declaration:
void foo( int i );
The definition can look like this:
void foo( const int i ) { ... }
Whether the variable 'i' is const or not on the definition side is an implementation detail. It has no impact for the clients of that function.

It probably doesn't care much about void Foo::foo(bar* const pBar) because how you treat the pointer itself (const or not) doesn't matter one bit outside of the routine. The C rules say that no change to pBar will travel outside of foo either way.
However, if it is (const bar* pBar), that makes a difference, because it means the compiler is not to allow callers to pass in pointers to non-const objects.

In the former, the const doesn't affect the interface, only the implementation. You are saying to the compiler, "I am not going to change the value of the bar* within this function". You can still change what is pointed to by the pointer. In the latter, you are telling the compiler (and all callers) that you will not change the bar structure that the bar* points to.

Related

What is the purpose of const here? [duplicate]

This question already has answers here:
Meaning of 'const' last in a function declaration of a class?
(12 answers)
Use of 'const' for function parameters
(31 answers)
Closed 2 years ago.
I've seen the following:
void function_name(std::string& txt) const;
What is the purpose of the const in the above prototype? The return type of the function is void so there is no return type, it looks completely pointless to me, I've seen this a lot, also when passing in parameters like:
void function_name(const int a);
Why would const add anything to the above, it cannot be changed in the function anyway if its not a pointer or reference?
void function_name(std::string& txt) const;
const mostly means this is a const member function and it's not supposed to change the state of the object. So if the function changes any of the member variables it will lead to compile error.
For the second case:
void function_name(const int a);
This const means that the function is not suppose to change variable a in its function body. Note, however, that const would not be required for basic type like int or bool. Also it's most likely applied when pass-by-reference (not pass by value like this).
So a typical usage would more like this:
void function_name(const some_non_trival_type& a);
That's said it's okay in the beginning without const.
void function_name(const int a)
{
int b = 10;
// complex things ...
std::cout<< a+b;
}
One day someone thought a new line would magically increase the performance of the function
void function_name(const int a)
{
a = 10; // Beep! It doesn't compile.
int b = 10;
// complex things ...
std::cout<< a+b;
}
Then this const save the world before any unit tests have been executed.
I'd say this const might have a semantic meaning to tell others "don't modify it because this function works properly according to parameter's constness".
The const method prototype enables you to use such method also for const objects like:
struct X
{
void function_name(std::string& txt) const {}
};
int main()
{
const X x;
std::string s{"Hallo"};
x.function_name(s); // will not work if the function is not marked as const!
}
The second case
void function_name(const int a);
gives the compiler a hint that you will ( and can ) never change the content of the const variable. That allows the compiler to optimize it. If you use a non trivial object like:
void function_name(const XYZ x);
it makes more sense, because if it is not const, the compiler must create a full copy of the object for that function. That may also be optimized out, but in case of const there is simply no need to take a copy as nothing will be altered. By standard clever compilers the internal generated code can be equivalent to:
void function_name(const XYZ& x);
or
void function_name(XYZ& x);
For the given example of using an int, it is has more or less no effect, but clarifies the interface.

Keyword 'const' on functions imply a full read-only of the object fields?

Having the following object
class Parser
{
public:
Parser(ComponentFactory * const factory): _factory(factory) {};
~Parser() = default;
void parse() const {
_factory->setFoo("foo");
}
private:
Factory * _factory;
};
My function parse() is specified as const. That's to say the function shouldn't modify the current object state and performs only read-only logics.
However, does the modification of the factory object imply a change of my current object's state? In other therms, is this even compilable?
I would like to understand why if yes, since I can't find any related subject on the net..
EDIT:
Since none can understand this, let me try to explain it better. In simple words, is the above code supposed to compile?
However, does the modification of the factory object imply a change of my current object's state?
No
In other therms, is this even compilable?
Yes.
I would like to understand why if yes, since I can't find any related subject on the net..
Say you have
struct Foo
{
int* ptr;
Foo() : ptr(new int(0)) {}
// It is valid since it does not change the state of Foo.
// It does not change where ptr points to. It just changes
// the value of what ptr points to.
void set(int value) const { *ptr = value; }
};
The compiler gives you the basic const characteristics. Higher level const-ness needs to be implemented by classes themselves.
In the case of Foo, if changing the value of what ptr to is deemed to change the state of Foo by the creator of Foo, then you'll have to remove const qualifier from the member function.
Marking a function as const means that you can't:
change any of the values of this's ivars
call a non-const function on this or any of its ivars
E.g. it would treat int foo; as const int foo;
These properties aren't transitive to pointers. Factory *_factory; doesn't become const Factory *_factory;, it becomes Factory *const _factory;, which is what you already have.
Imagine if you were using a smart pointer instead, would you expect the compiler to know that it should convert std::shared_ptr<Factory> _factory; into std::shared_ptr<const Factory> _factory;? All it would do is treat it as const std::shared_ptr<Factory> _factory;

How should I specify the constness of a constructor argument to a pointer member

Basically I want to have a simple class that wrap a pointer (i.e. has a pointer member) and I don't know how to specify the constness of the constructor arguments. If I do this
class A {
public:
A(int *d) : data(d) {}
private:
int *data;
};
Then I can't do this
void func(const int *param) {
const A aInstance(param);
}
because the constructor doesn't take a const pointer.
I want to be able to construct const objects and take const pointers to do it, but I also want to be able to construct non-const objects that modify the pointer. How do I specify this class so that I can modify *data when it's relevant, but I can construct a const object what that is relevant?
Your constructor should take a pointer which points to a constant object:
A(const int *d) : data(d) {}
You have a key misconception here: The compiler is warning you that you're passing a pointer to a const int into an object which might try to change the int's value. Declaring const A doesn't fix that problem because, while data cannot change, the thing that data points to still can.
The solution you need has already been provided by others in the comments:
If A doesn't need to modify *data then you should declare it's member variable as const int *data.
Otherwise you'll need to provide two versions: A and const_A. You could type out two separate definitions or use templates so you only have to type it out once.
If you know that your usage is safe and you want to live dangerously then you could use const_cast to remove the constness and thwart the compiler's warning.
The only answer that seems to satisfactorily maybe answer the question is a comment from #JohnAuld who suggested I template the class thusly
template< typename data_t >
class A
{
public:
A(data_t *data) : d(data) {}
private:
data_t *d;
};
In theory this would work well to construct a constable object, and it even lets me create const and non-const methods for which compilation will fail if I try to assign something to the data pointed to by d for const objects. That's all fine and dandy. It even let's me do what I wanted:
void doSomething(const int *somePointer) {
A<const int> a(somePointer);
}
However, where it fails is to use const specifiers on the class. If I wanted to pass the subsequent const object to another function, it would fail:
void doSomethingToAnA(const A<int> &a);
void doSomethingToIntPointer(const int *aPointer) {
const A<int> aInstance(aPointer);
doSomethingToAnA(aInstance);//womp womp
}
basically const A<int> != A<const int>

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()

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

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.