c++ 为什么我被告知“这个方法可以是const”?

6ss1mwsb  于 2023-06-25  发布在  其他
关注(0)|答案(3)|浏览(139)

在一个班级里

  1. class Foo
  2. {
  3. public:
  4. void DoSomething(int x) const;
  5. private:
  6. int m_bar;
  7. };

不允许写

  1. void Foo::DoSomething(int x) const
  2. {
  3. m_bar = x; // Error
  4. }

我必须删除const修饰符,但是,如果我有

  1. struct Data
  2. {
  3. bar;
  4. };
  5. class Foo
  6. {
  7. public:
  8. void DoSomething(int x) const;
  9. private:
  10. Data * m_data;
  11. };
  12. void Foo::DoSomething(int x) const
  13. {
  14. m_data->bar = x;
  15. }

那么这不仅没问题,而且如果我删除修饰符,代码验证工具会警告我“方法可以是常量”?
我不应该在const方法中修改对象的状态,不管状态是如何表示的!

x7yiwoj4

x7yiwoj41#

const限定符告诉编译器该函数不会修改对象的任何成员变量。因此,如果你有一个指针成员变量,const函数将无法改变指针本身。

***但***只适用于实际成员变量。指针实际指向的数据不是常量。为此,您需要一个指向常量对象的指针(例如Data const* m_data;)。

nfzehxib

nfzehxib2#

指针指向某处。如果你修改一个指针,你就修改了它指向的地方。
因为指针指向某个地方,所以可以取消引用它们来访问被指针。修改指针对象不会修改指针。
为了便于说明,假设你没有指针,而是有一个数组的索引:

  1. struct Data
  2. {
  3. int x;
  4. };
  5. Data my_memory[42];
  6. class Foo
  7. {
  8. public:
  9. void DoSomething(int x) const;
  10. private:
  11. size_t m_index; // "points to" a Data element in my_memory
  12. };
  13. void Foo::DoSomething(int x) const
  14. {
  15. my_memory[m_index].x = x;
  16. }

当然指针不是数组的索引。虽然作为心理图像,它比你想象的更准确。索引引用存储在别处的实际对象。可以修改对对象没有影响的索引。您可以使用索引访问对象并修改它,而无需修改索引。这和你的指针是一样的。
我希望现在很明显Foo::DoSomething应该是const。您正在修改Data对象,该对象不是Foo的一部分。Foo只包含指向对象的指针。DoSomething不会修改该指针。

展开查看全部
mcvgt66p

mcvgt66p3#

对象在某个地址P占用某个X内存。带有const限定符的成员函数不能DIRECTLY更改此地址的内存X,这就是为什么函数可以标记为const
在下面的例子中,我们CAN改变const对象中对象的内存

  1. struct A {
  2. public:
  3. A(): x(5) { x_p =&x;};
  4. void update_x() const { *x_p = 3;}
  5. int x;
  6. int *x_p;
  7. };

编译并运行:

  1. int main()
  2. {
  3. A a;
  4. std::cout << a.x << std::endl;
  5. a.update_x();
  6. std::cout << a.x << std::endl;
  7. }

将得到:

  1. 3
  2. 5
展开查看全部

相关问题