对我的一篇帖子的评论引起了我的兴趣:
我也是。我还给访问器/修改器赋予相同的名称。
我想知道这一点,因为我一直使用
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 正确性很重要,所以我想我希望编译器反对重载,因为一个会变异,一个不会。
为什么会这样?
编译器首先查看的是传递给函数的参数的数量和类型。这在需要查看
bar
-ness 之前就解决了 const
上的过载问题。
如果您未能将
bar()
标记为 const
,编译器会在您第一次尝试在对象的 bar()
实例上调用 const
时通知您。
编译器不会阻止您编写实际上不会改变对象的非常量成员函数。这并不违反 const 正确性,它只是确保对象不会通过 const 引用而发生变化。这里的原则是 const 表示函数不能变异,non-const 表示函数可以随意变异。没有办法承诺改变,并让编译器强制执行:我认为这对于调用者来说太模糊了,没有任何用处。
正如 Greg 所说,当你尝试在 const 对象上调用非常量成员函数时,编译器会反对(同样,它是否实际上发生变化并不重要。唯一重要的是它是否被声明为 const)。
为了更容易理解,请考虑编译器假设如果为该对象调用非常量方法,则该对象将被更改。
因此,在 const 方法中,如果您为某个数据成员调用非常量方法或类的另一个非常量方法,编译器将发出错误信号。
您也可以将运算符视为方法(我知道,您可以将某些运算符定义为友元函数,而不是方法,而是为了简化......)。例如,赋值运算符 (operator=) 默认情况下是非常量运算符。这意味着如果你做类似的事情
void MyClass::MyConstMethod() const
{
classMember = value;
}
编译器会认为你调用了classMember的赋值运算符,它在const方法中是一个const对象。由于operator=不是const,所以会报编译错误。