为什么我可以从 const 方法调用更改成员的方法?

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

我不太明白为什么我可以从 const 方法修改一个对象,请看:

#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";

}

不仅编译而且打印:

0
3

所以我能够从 const 方法修改对象的逻辑状态。那是因为我使用了指针吗?

const 适用于指针本身,f,不适用于此指针指向的对象。 const 限定成员函数 Test::test()f 的类型是 Foo* const (即 const 指向 Foo),而不是 const Foo*(即 指向 const Foo 的指针)。这就是为什么你可以修改指针指向的内容,尽管成员函数的 const 限定。


请注意,以下示例成员函数 Test::test2() 确实无法编译,因为它是 const 限定的并尝试修改指针数据成员 f

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

不,您没有修改对象的逻辑状态:

    f->change();

f,对象的 class 成员,一如既往地在这里。它的值没有改变。它现在不指向其他对象。它仍然指向它一直指向的同一个对象。

你修改的是f指向的对象。这是一个不同的对象。

是的,您修改了对象的逻辑状态。这是允许的,因为 const 禁止修改 physical 状态。

对象 t 有一个数据成员 f,类型为 "pointer to Foo"。创建 t 对象时,它的 f 成员指向类型 Foo 的对象。在调用 t.test() 之后,f 成员仍然持有相同的地址,因此它指向与之前相同的 Foo 类型的对象。

如果test()试图改变存储在f中的(即指针),const会阻止它.

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