[英]How does the compiler determine which member functions mutate?
对我的其中一篇帖子的评论使我感兴趣:
我也是 。 我也给访问者/更改者同一个名字。
我对此很疑惑,因为我一直使用setBar(int bar)
代替同名的mutator。 我想知道:编译器可以基于const标识符确定运行时会发生什么变化,还是可以使用相同的函数名,因为它具有参数?
可以编译吗:
class Foo
{
int bar_;
public:
int bar() { return bar_; }
void bar(int bar) { bar_ = bar; }
}
还是我必须这样做(我意识到无论如何我都应该这样做,只要和我一起运行):
int bar() const { return bar_; }
我不知道是哪个。 const的正确性很重要,因此我认为我希望编译器反对重载,因为一个突变而另一个则不会。
为什么这样工作?
编译器首先查看的是传递给函数的参数的数量和类型。 这可以解决bar
上的重载,甚至不需要查看const
-ness。
如果您未能将bar()
标记为const
,则在您首次尝试在对象的const
实例上调用bar()
时,编译器会通知您。
编译器不会阻止您编写实际上不会使对象变异的非常量成员函数。 这并不违反const正确性,后者只能确保对象不会通过const引用进行变异。 此处的原理是const表示该函数不能进行更改,而非const表示该函数可以随意进行更改。 没有办法保证会发生突变,而让编译器强制这样做:我认为这对于保证调用者没有任何用处的保证太含糊。
正如Greg所说的,当您尝试在const对象上调用非const成员函数时,编译器将成为对象(再次,实际上是否突变无关紧要。唯一重要的是是否将其声明为const)。
为了更容易理解,请考虑编译器假定,如果为该对象调用非const方法,则该对象将被更改。
因此,在const方法中,如果您为数据成员之一或类的另一个非const方法调用非const方法,则编译器将发出错误信号。
您也可以将运算符视为方法(我知道,您可以将某些运算符定义为友好函数,而不是方法,而是为了简化...)。 例如,赋值运算符(operator =)默认为非常量。 这意味着如果您做类似的事情
void MyClass::MyConstMethod() const
{
classMember = value;
}
编译器会认为您调用了classMember的赋值运算符,该运算符在const方法内部是const对象。 由于operator =不是const,将报告编译器错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.