【问题标题】:Cannot access protected member of another instance from derived type's scope无法从派生类型的范围访问另一个实例的受保护成员
【发布时间】:2023-08-24 06:25:01
【问题描述】:

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 实例的受保护成员DerivedBase 不同的事实?铊;博士:在这种情况下,是什么让protectedprivate 更“私密”?

注意事项

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

【问题讨论】:

  • 访问说明符的工作方式相同,即使您在范围内看到对象。您使用Base 引用,这就是她所写的全部内容。

标签: c++ language-lawyer encapsulation protected


【解决方案1】:

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

如果 [...]

  • m 作为 N 的成员受到保护,并且 R 出现在 N 类的成员或朋友中,或在派生自 N 的类 P 的成员中,其中m 作为P 的成员是publicprivateprotected

里面有很多字母。但基本上有两个条件:

  1. R 是班级的成员或朋友。这将处理 d.prot 示例 - 我们在访问 Derived 的受保护成员时位于 Derived 的成员中。
  2. R 在派生类的成员中,并且被访问的成员是派生类实例的成员。这处理 b.prot 示例 - 我们在派生类的成员中,但 prot 不是派生类的成员。

换句话说,Derived 可以访问Base 的受保护成员 - 但仅限于它正在访问其自己的子对象的受保护成员的情况。它不能访问其他Base 对象的受保护成员。当您考虑到另一个 Base 很容易成为 SomeOtherDerived 时,这是有道理的,在这种情况下,这只是另一个与我们无关的对象,我们没有特殊的访问权限。

【讨论】:

  • 这个答案确认protected访问说明符并不像privatepublic那么简单!