C ++嵌套结构继承规则(访问受保护成员)

时间:2017-01-17 14:54:57

标签: c++ inheritance language-lawyer protected

任何人都可以向我解释为什么(例如,“为什么语言是这样的?”)以下代码在B::C::bar的第二行有编译错误?

class A
{
public:
    struct D
    {
        void call_foo (A &a)
        {
            a.foo ();
        }
    };

protected:
    void foo () {}
};

class B : public A
{
    struct C : public A::D
    {
        void bar (A &a, B &b)
        {
            b.foo (); // OK
            a.foo (); // Error. Huh?
            call_foo (a); // Ugly workaround
        }
    };
};

当且仅当基指针的类型恰好是封闭类型(而不是某些父类型)时,方法似乎可以安全地在父类中使用受保护的方法。

这似乎很奇怪。为什么这种语言会这样?

1 个答案:

答案 0 :(得分:8)

struct C嵌套在类B中,它被注册为成员,因此它具有与任何其他成员相同的访问权限。所以是的,它可以访问基类protected的{​​{1}}成员。但请注意,您只能通过A类型的对象访问protected A成员;你不能通过B来做到这一点。这是有道理的,因为派生类的成员应该只能访问从基类继承的A成员;这些成员属于派生类。但是不应该允许直接访问基类的protected成员;它们属于基类(或其他派生类)。

规则对于内部类并不特殊,对protected的成员函数也是如此。

§11.4/1 Protected member access [class.protected]

(强调我的)

  

除了前面条款中描述的那些之外的附加访问检查   [class.access]在非静态数据成员或非静态时应用   member function是其命名类的受保护成员   ([class.access.base])115如前所述,访问受保护的   成员被授予,因为引用发生在朋友或成员中   一些C级。如果访问是形成指向成员的指针   ([expr.unary.op]),嵌套名称说明符应表示C或类   源自C. 所有其他访问涉及(可能是隐含的)   对象表达式([expr.ref])。在这种情况下,对象的类   表达式应为C或源自C 的类。 [实施例:

B
     

- 结束示例]