c ++如何为同一成员创建公共和受保护的访问器

Posted

技术标签:

【中文标题】c ++如何为同一成员创建公共和受保护的访问器【英文标题】:c++ how to create public and protected accessors to same member 【发布时间】:2016-09-03 09:02:50 【问题描述】:

如果我有两种方法——一种是公共的,一种是保护的,返回对同一成员的引用,我会得到以下编译错误:

'Server::getManager': cannot access protected member declared in class 'Server'

当我注释掉受保护的函数时,代码可以工作。你能告诉我为什么会这样吗?为什么编译器找不到同一成员的公共函数?

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;

【问题讨论】:

编译器找到公共的,但保护的更好。它完全匹配。 如果公共的返回相同的东西,你为什么需要受保护的? 访问说明符在重载决议后评估。所以编译器首先找到最佳匹配,然后然后检查它是否可以访问。我建议您简单地重命名受保护的成员,因为您显然打算在不同的上下文中使用它。 @wizzardmr42,因为类或它的派生类可能想要修改管理器并且是正确的。在这里也使用访问器函数,具有无需修补整个代码库即可更改实现的相同好处。 【参考方案1】:

为什么编译器找不到同一成员的公共函数?

这不是问题。编译器找到 both 函数并执行重载决议以确定哪个是最佳可行候选者。两位候选人是:

Manager&       getManager()        // protected
Manager const& getManager() const  // public

对于成员函数,有一个隐式的第一个对象参数,即类本身的实例。在这种情况下,这两个函数变为:

getManager(Server& )         // protected
getManager(Server const& )   // public

我们在一个不是 const 的对象 (s) 上调用它。两个候选者都是可行的,但 public 候选者比 protected 候选者引用了一个 more cv 限定对象 - 所以它不太受欢迎。标准版在 [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();

这将使protected 候选人不可行。

【讨论】:

或者调用受保护的getWritableManager。你没有重载函数。

以上是关于c ++如何为同一成员创建公共和受保护的访问器的主要内容,如果未能解决你的问题,请参考以下文章

经典.net面试题目

内部类的使用类型

16. 在.NET中,一个页面对象是( )类的实例。

Java设计模式——单例模式(创建型模式)

如何用Lua来访问Unity 控件的属性

如何为 NSManagedObject 子类编写自定义访问器?