编译器如何确定哪些成员函数发生变异?

问题描述 投票:0回答:3

对我的一篇帖子的评论引起了我的兴趣:

我也是。我还给访问器/修改器赋予相同的名称。

我想知道这一点,因为我一直使用

setBar(int bar)
而不是命名相同的变体。我想知道:编译器可以根据 const 标识符确定运行时发生的变化,还是可以使用相同的函数名,因为它有一个参数?

这个编译好吗:

class Foo
{
   int bar_;

   public:
      int bar() { return bar_; }
      void bar(int bar) { bar_ = bar; }
}

或者我必须这样做吗(我意识到无论如何我都应该这样做,就跟我一起做吧):

int bar() const { return bar_; }

我不知道哪个是哪个。 const 正确性很重要,所以我想我希望编译器反对重载,因为一个会变异,一个不会。

为什么会这样?

c++ overloading
3个回答
4
投票

编译器首先查看的是传递给函数的参数的数量和类型。这在需要查看

bar
-ness 之前就解决了
const
上的过载问题。

如果您未能将

bar()
标记为
const
,编译器会在您第一次尝试在对象的
bar()
实例上调用
const
时通知您。


2
投票

编译器不会阻止您编写实际上不会改变对象的非常量成员函数。这并不违反 const 正确性,它只是确保对象不会通过 const 引用而发生变化。这里的原则是 const 表示函数不能变异,non-const 表示函数可以随意变异。没有办法承诺改变,并让编译器强制执行:我认为这对于调用者来说太模糊了,没有任何用处。

正如 Greg 所说,当你尝试在 const 对象上调用非常量成员函数时,编译器会反对(同样,它是否实际上发生变化并不重要。唯一重要的是它是否被声明为 const)。


0
投票

为了更容易理解,请考虑编译器假设如果为该对象调用非常量方法,则该对象将被更改。

因此,在 const 方法中,如果您为某个数据成员调用非常量方法或类的另一个非常量方法,编译器将发出错误信号。

您也可以将运算符视为方法(我知道,您可以将某些运算符定义为友元函数,而不是方法,而是为了简化......)。例如,赋值运算符 (operator=) 默认情况下是非常量运算符。这意味着如果你做类似的事情

void MyClass::MyConstMethod() const
{
   classMember = value;
}

编译器会认为你调用了classMember的赋值运算符,它在const方法中是一个const对象。由于operator=不是const,所以会报编译错误。

© www.soinside.com 2019 - 2024. All rights reserved.