【发布时间】:2015-03-05 13:26:59
【问题描述】:
给定以下代码:
class A
{
public:
A(): value( 0 ) {}
int* get()
{
return &value;
}
const int& get() const
{
return value;
}
private:
int value;
};
int main()
{
A a;
const int& ref_value = a.get();
}
导致以下编译错误:
prog.cpp: In function 'int main()':
prog.cpp:23:35: error: invalid conversion from 'int*' to 'int'
const int& ref_value = a.get();
^
似乎带有 const 修饰符的重载 get() 方法确实被完全忽略了,编译器只看到它的非常量定义。这是可以理解的,因为 a 对象不是恒定的。一种解决方案是使 a 对象保持不变。尽管还有其他两种使代码可编译的解决方案:
-
更改 const get() 方法的签名通过不同的名称或其他添加的参数。
int* get(); const int& get_changed() const; <-- this gets called -
更改非常量 get() 方法以返回引用而不是指针。
int& get(); <-- this gets called const int& get() const;
虽然有
int* get();
const int& get() const;
我们有一个编译器错误。
令我困惑的是所有这些行为背后的原因。
【问题讨论】:
-
为什么会令人费解?如果在非常量对象上调用
const方法,会不会更加令人费解? -
是的,这恰好发生在我提到的那两种情况下(const 方法在非常量对象上被调用),所以它仍然令人费解。
-
如果只有一个 const 方法,则不需要执行重载决议。只能调用 const 方法。如果有两个重载,则为非常量对象选择非常量,反之亦然。我并不觉得这特别令人费解。
-
为什么会出现编译错误?为什么不为非常量对象选择 const 方法而不是给出编译错误?
-
在 SO 中搜索一些信息,我发现其基本原理与 C++ 的强类型有关。让返回类型成为函数签名的一部分有效地使返回值的隐式/显式转换成为一场灾难。就像这里的评论一样,如果返回值被丢弃怎么办? stackoverflow.com/questions/9568852/overloading-by-return-type
标签: c++ reference overriding constants