如果我有两个方法 - 一个public,一个protected返回对同一个成员的引用,我得到以下编译错误:
'Server::getManager': cannot access protected member declared in class 'Server'
Run Code Online (Sandbox Code Playgroud)
当我注释掉受保护的功能时,代码可以工作.你能告诉我为什么会这样吗?为什么编译器找不到同一个成员的公共函数?
class Manager
{
};
class Server
{
public:
const Manager & getManager() const { return m_man; }
protected:
Manager & getManager() { return m_man; } // <-- after removing this method I get no compilation error
private:
Manager m_man;
};
int main()
{
Server s;
const Manager& m = s.getManager();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器找不到同一个成员的公共函数?
那不是问题.编译器找到这两个函数并执行重载决策以确定哪个是最佳可行候选者.两位候选人是:
Manager& getManager() // protected
Manager const& getManager() const // public
Run Code Online (Sandbox Code Playgroud)
对于成员函数,有一个隐含的第一个对象参数,它是类本身的实例.在这种情况下,这两个函数变为:
getManager(Server& ) // protected
getManager(Server const& ) // public
Run Code Online (Sandbox Code Playgroud)
我们在一个s不是的对象()上调用它const.两位候选人都可行,但public候选人需要一个参考更多的 CV -qualified对象不是protected候选人-所以这是优选的.标准是[over.ics.rank]:
标准转换序列S1是比标准转换序列S2更好的转换序列,如果
-S1和S2是引用绑定(8.5.3),并且引用引用的类型是除了顶级cv限定符之外的相同类型,并且由S2引用的引用引用的类型比由S1引用的引用引用的类型更具cv限定.
因此,protected候选人是首选 - 所以这就是所谓的候选人.
不幸的是,它是protected,所以称它是不正确的.重载解决后检查访问控制.所以你必须以某种方式重组你的程序.你可以简单地投射s到const:
const Manager& m = const_cast<Server const&>(s).getManager();
Run Code Online (Sandbox Code Playgroud)
这将使protected候选人无法生存.