无法从派生类型的范围访问另一个实例的受保护成员

时间:2017-07-17 13:47:53

标签: c++ language-lawyer encapsulation protected

this answer中的问题“为什么我的对象不能访问公共基类中定义的另一个对象的受保护成员?”,可以阅读:

  

您只能从自己的基类实例访问受保护的成员。

要么我没弄错,要么following MCVE (live on coliru)证明错了:

struct Base           { void f(); protected: int prot; };
struct Derived : Base { void g(); private:   int priv; };

void Base::f()
{
    Base b;
    b.prot = prot;
    (void) b;
}

void Derived::g()
{
    {
        Derived d;
        (void) d.priv;
    }

    {
        Derived& d = *this;
        (void) d.priv;
    }

    {
        Derived d;
        (void) d.prot; // <-- access to other instance's protected member
    }

    {
        Derived& d = *this;
        (void) d.prot;
    }

    // ---

    {
        Base b;
        (void) b.prot; // error: 'int Base::prot' is protected within this context
    }

    {
        Base& b = *this;
        (void) b.prot; // error: 'int Base::prot' is protected within this context
    }
}

根据这两个错误,我想知道:为什么我可以从Derived的范围访问另一个Derived实例的受保护成员,但无法访问另一个Base实例的受保护成员不管Derived来自Base的事实,来自同一范围的成员? TL;博士:在这种情况下,protectedprivate更加“私密”的原因是什么?

备注

  • 请不要将此问题作为链接问题的副本关闭;
  • 欢迎更好的标题建议。

1 个答案:

答案 0 :(得分:3)

[class.access.base]中的规则是:

  

如果[...]

,则在{em> R 点可以访问成员m      
      
  • N作为m的成员受到保护,而 R 出现在班级N的成员或朋友中,或者出现在班级成员中来自N的{​​{1}} P N成员为mPpublic
  •   

那里有很多信件。但基本上有两个条件:

  1. private是该班级的成员或朋友。这会处理protected示例 - 我们在访问R的受保护成员时属于d.prot成员。
  2. Derived位于派生类的成员中,被访问的成员派生类实例的成员。这处理Derived示例 - 我们是派生类的成员,但R不是派生类的成员。
  3. 换句话说,b.prot可以访问prot的受保护成员 - 但仅限于访问其自己的子对象的受保护成员的情况。它无法访问其他Derived对象的受保护成员。如果您认为其他Base可能很容易Base,这是有道理的,在这种情况下,这只是我们没有特殊访问权限的另一个无关对象。