Voko
Voko

Reputation: 778

Why can I call a method that changes a member from a const method?

I'm not sure to understand why I can modify an object from a const method, look:

#include <iostream>

struct Foo {
    int a = 0;
    void change() {
        a = 3;
    }
};

struct Test {
    Foo* f;

    Test(): f{new Foo} {}

    void test() const {
        f->change();
    }
};

int main()
{
  Test t;
  std::cout << "before: " << t.f->a << "\n";
  t.test();
  std::cout << "after: " << t.f->a << "\n";

}

Not only it compiles but it prints:

0
3

So I was able to modify the logical state of an object from a const method. Is that because I used a pointer?

Upvotes: 4

Views: 81

Answers (3)

Pete Becker
Pete Becker

Reputation: 76513

Yes, you modified the logical state of the object. That's allowed, because const prohibits modifying the physical state.

The object t has one data member, f, whose type is "pointer to Foo". When the t object is created, it's f member points at an object of type Foo. After the call t.test() the f member still holds the same address, so it points at the same object of type Foo as it did before.

If test() had tried to change the value stored in f (i.e., the pointer) the const would have prevented it.

void Test::test() const { f = new Foo; } // error: `f` is const in this context

Upvotes: 1

jfMR
jfMR

Reputation: 24788

The const applies to the pointer itself, f, not to what this pointer is pointing to. The type of f inside your const-qualified member function, Test::test(), is Foo* const (i.e., const pointer to Foo), not const Foo* (i.e., pointer to const Foo). That's why you can modify what the pointer is pointing to in spite of the const qualification of the member function.


Note that the following sample member function, Test::test2(), does fail to compile since it is const-qualified and tries to modify the pointer data member, f:

void Test::test2() const {
        f = nullptr; // <-- error
}

Upvotes: 4

Sam Varshavchik
Sam Varshavchik

Reputation: 118435

No, you did not modify the logical state of an object:

    f->change();

f, the object's class member, is as it's always been, here. Its value hasn't changed. It's not pointing to some other object now. It's still pointing to the same object it's always been pointing to.

What you did modify is the object to which f points to. Which is a different object.

Upvotes: 1

Related Questions