Hippo
Hippo

Reputation: 115

C++ const problems when member value is changed from pointer to non-pointer

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

Answers (4)

Rafał G&#243;rczewski
Rafał G&#243;rczewski

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

Bob Bills
Bob Bills

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

R Sahu
R Sahu

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

eerorika
eerorika

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

Related Questions