在非常量对象上,为啥 C++ 不调用具有 public-const 和 private-nonconst 重载的方法的 const 版本?

Posted

技术标签:

【中文标题】在非常量对象上,为啥 C++ 不调用具有 public-const 和 private-nonconst 重载的方法的 const 版本?【英文标题】:On a nonconst object, why won't C++ call the const version of a method with public-const and private-nonconst overloads?在非常量对象上,为什么 C++ 不调用具有 public-const 和 private-nonconst 重载的方法的 const 版本? 【发布时间】:2014-10-08 14:53:01 【问题描述】:
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 方法?

【问题讨论】:

【参考方案1】:

对象不是const,所以非const重载是更好的匹配。重载解决发生在访问检查之前。这可确保重载决议不会因更改成员函数的访问而意外更改。

【讨论】:

原因是设计者认为查找和解析依赖于访问检查会很容易出错;将方法从公共更改为私有可能会导致该函数的使用无声地切换到其他函数,而这并不是本意。【参考方案2】:

来自标准:

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

【讨论】:

即C++ 中的查找语义就像不存在访问检查一样适用。然后应用访问检查。访问检查不会影响可见性和选择,只会影响权限。 因此类外部的代码可以通过添加私有成员函数来中断。外部代码取决于类内部。 @usr 但是你得到一个编译器错误。如果不是这样,当您更改成员函数的访问权限时,代码的行为可能会悄无声息地发生变化。 @juanchopanza 导致编译器错误是一项重大更改。如果 C 在库中,则该库必须仔细命名其私有成员,以免在库更新时导致依赖代码中断。 @usr 改变行为也是一个重大改变。最好早点失败。但在实际代码中,您不应该有具有不同访问权限的重载。

以上是关于在非常量对象上,为啥 C++ 不调用具有 public-const 和 private-nonconst 重载的方法的 const 版本?的主要内容,如果未能解决你的问题,请参考以下文章

为啥此 C++ 代码仅在 Microsoft 编译器上具有模棱两可的方法调用?

C++ 为啥非常量数组声明不好? [复制]

为啥常量整数指针指向允许的非常量整数?

为啥我可以在临时 std::ofstream 对象上使用 `operator<<`?

C++ 常量引用非常量对象和非常量引用非常量对象之间的区别

从具有相同基的另一个派生类调用派生类的非常量方法