在一个非const对象上,为什么C++不会调用具有公共const和私有非const重载的成员函数的const版本?

27
class C
{
public:
    void foo() const {}
private:
    void foo() {}
};

int main()
{
    C c;
    c.foo();
}

MSVC 2013 不喜欢这个:
> error C2248: 'C::foo' : cannot access private member declared in class 'C'

如果我将其转换为一个`const`引用,它就可以工作了。
const_cast<C const &>(c).foo();

为什么我不能在非const对象上调用const成员函数?
2个回答

24

这个对象不是const,所以非const的重载函数更匹配。函数重载解析发生在访问检查之前。这确保了函数重载解析不会因更改成员函数的访问权限而意外改变。


18
设计师们的想法是查找和解析不应该依赖于访问检查,因为这样容易出错。将一个方法从公有改为私有可能会导致使用该函数的地方静默地切换到其他函数,而这并不是设计者的本意。 - bames53

22

根据标准:

13.3.3 如果存在最佳可行函数并且是唯一的,重载解析成功并将其作为结果生成。 否则,重载解析失败并且调用无效。 当重载解析成功时, 最佳可行函数在使用它的上下文中不可访问(第11条),程序无效。


12
在C++中,查找语义似乎好像不存在访问检查一样。然后再应用访问检查。访问检查不影响可见性和选择,只影响权限。 - Kaz
因此,类外部的代码可能会通过添加私有成员函数而中断。外部代码依赖于类内部。 - usr
@usr 但是你会得到一个编译器错误。如果不是这样,当你改变成员函数的访问权限时,代码的行为可能会悄无声息地发生变化。 - juanchopanza
@juanchopanza 引起编译器错误是一种破坏性的变化。如果 C 在一个库中,那么该库必须仔细命名其私有成员,以避免在库更新时导致依赖代码出现故障。 - usr
2
更改行为也是一种破坏性的变化。最好尽早失败。但在实际代码中,不应该有具有不同访问权限的重载。 - juanchopanza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接