访问受保护的基类构造函数

Bri*_*ian 10 c++ oop language-lawyer

派生类可以在其ctor-initializer中调用受保护的基类构造函数,但仅适用于其自己的基类子对象,而不是其他地方:

class Base {
  protected:
    Base() {}
};

class Derived : Base {
  Base b;
  public:
    Derived(): Base(),    // OK
               b() {      // error
        Base b2;          // error
    }
};
Run Code Online (Sandbox Code Playgroud)

标准对此有何看法?这是[class.protected]/1:

当非静态数据成员或非静态成员函数是其命名类的受保护成员时,将应用超出第11章中所述之外的其他访问检查(11.2)如前所述,授予对受保护成员的访问权限,因为引用发生在朋友或某个类的成员中C.如果访问要形成指向成员的指针(5.3.1),则嵌套名称说明符应表示C或派生自的类C.所有其他访问都涉及(可能是隐式的)对象表达式(5.2.5).在这种情况下,对象表达式C的类应该是派生自的类C.[ 例子: ......

调用构造函数时是否涉及对象表达式?没有,有吗?那么标准中的哪个位置描述了受保护的基类构造函数的访问控制?

Mar*_*k B 3

protected访问权限仅适用于您自己的当前对象类型的父成员。您无法获得对父类型其他对象的受保护成员的公共访问权限。在您的示例中,您只能访问作为 a 一部分的默认基本构造函数Derived,而不是当它是作为 的独立对象时b

让我们分解一下您发布的标准 (11.4/1) 的报价。我们假设C标准中对应于您的Derived班级:

当非静态数据成员或非静态成员函数是其命名类 (11.2) 的受保护成员时,将应用第 11 条前面描述的附加访问检查。

因此,基类构造函数实际上是non-static member function其命名类 ( B) 的一个,因此该子句到目前为止都适用。

如前所述,授予对受保护成员的访问权限是因为引用发生在某个 C 类的友元或成员中。

C所以我们这里还是很好的成员(构造者) 。

如果访问是为了形成指向成员的指针 (5.3.1),则嵌套名称说明符应表示 C 或从 C 派生的类。

这不是指向成员的指针,因此这不适用。

所有其他访问都涉及(可能是隐式的)对象表达式 (5.2.5)。

然后,该标准断言所有其他可能的访问都必须涉及对象表达式。

在这种情况下,对象表达式的类应为 C 或从 C 派生的类。

最后,标准规定表达式的类必须是C或更进一步的派生类。在这种情况下,您的表达式Base()实际上是 a C,调用父构造函数(将其视为this->Base()。该表达式b显然是类型Base(这是成员的显式声明类型b,请考虑this->b->Base())。现在我们进行检查:是BaseaC或 child的C? 它不是,所以代码不合法​​。