Reputation: 115
I have two classes TestClass
and OtherClass
, where TestClass
has a member variable of type OtherClass
named m_otherClass
. Note that this is not declared to be const.
In the minimal example provided below; when m_otherClass
is a pointer, then everything compiles and runs fine. If I change this to be a non-pointer, then I get compiler errors (the changes are commented out in the minimal example):
"Non-const function 'setOtherMember' is called on const object"
error: passing 'const OtherClass' as 'this' argument discards qualifiers [-fpermissive] m_otherClass.setOtherMember();
#include <iostream>
#include <memory>
class OtherClass {
public:
void setOtherMember() {
m_otherMember = 2;
std::cout << "Other member is now 2" << std::endl;
}
private:
int m_otherMember = 0;
};
class TestClass {
public:
TestClass(): m_otherClass(std::make_unique<OtherClass>())
// TestClass()
{}
void myMethod() const {
m_otherClass->setOtherMember();
// m_otherClass.setOtherMember();
}
private:
std::unique_ptr<OtherClass> m_otherClass;
// OtherClass m_otherClass; // If changing to this I get the error!!
};
int main() {
TestClass testClass;
testClass.myMethod();
return 0;
}
Is this because myMethod()
is const (and then promising not to change any member variables), whereas setOtherMember()
is non-const and is changing OtherClass
's member variable, and then indirectly also the m_otherClass
object?
But why does this not fail then when m_otherClass
is a pointer?
And why does the compiler error says that passing 'const OtherClass' as 'this'argument fails, when m_otherClass
has not been declared to be const?
Upvotes: 2
Views: 122
Reputation: 151
Const qualified member functions in most cases aren't allowed to change an object's members state. This means, that every member which is not mutable can not be modified in this function body. When dealing with pointers, you just say, that you won't modify a pointer value, not a pointee itself. It is because constness of a pointer is not propagated on its pointee.
In the upcoming standards it will be possible to change this behaviour by using propagate_const.
Upvotes: 3
Reputation: 519
When you put const on a method, all your data members are treated as being const. And that is why you get the error when you have OtherClass as a value, since it turns into a value of const OtherClass
.
Now when you use a pointer of OtherClass
you get const std::unique_ptr<OtherClass>
and the const applies only to the pointer but not to the value it points to.
Upvotes: 1
Reputation: 206557
A simpler example to demonstrate the difference.
struct Foo { int m; };
const Foo f = {10};
f.m = 20; // Not allowed since modifying f.m modifies f.
struct Bar { int* p; };
int i = 10;
int j = 20;
const Bar b = {&i};
b.p = &j; // Not allowed since modifying b.p modifies b.
*(b.p) = j; // Allowed since it does not change b or b.p. It changes the value
// of what b.p points to.
Upvotes: 2
Reputation: 238281
But why does this not fail then when
m_otherClass
is a pointer?
Because it is const correct to modify an object pointed by a const pointer, as long as it is a pointer to non-const such as in your case.
And why does the compiler error says that passing 'const OtherClass' as 'this'argument fails, when m_otherClass has not been declared to be const?
myMethod
is declared const. Therefore this
is a pointer to const. Therefore the lvalue this->m_otherClass
is also const regardless of whether the object named by the lvalue is const or not.
Upvotes: 1