Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 访问基类的受保护构造函数_C++_Oop_Language Lawyer - Fatal编程技术网

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

C++ 访问基类的受保护构造函数,c++,oop,language-lawyer,C++,Oop,Language Lawyer,派生类可以在其ctor初始值设定项中调用受保护的基类构造函数,但只能为其自己的基类子对象调用,而不能在其他地方调用: class Base { protected: Base() {} }; class Derived : Base { Base b; public: Derived(): Base(), // OK b() { // error Base b2; // error

派生类可以在其ctor初始值设定项中调用受保护的基类构造函数,但只能为其自己的基类子对象调用,而不能在其他地方调用:

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

class Derived : Base {
  Base b;
  public:
    Derived(): Base(),    // OK
               b() {      // error
        Base b2;          // error
    }
};
标准对此有何规定?下面是[class.protected]/1:

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


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

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

让我们将您从标准(11.4/1)中发布的报价细分。我们将假设标准中的
C
对应于您的
派生类:

除第11条前面所述之外的额外访问检查 当非静态数据成员或非静态成员函数 是其命名类(11.2)的受保护成员

因此,基类构造函数实际上是其命名类(
B
)的
非静态成员函数,因此本条款适用于目前为止

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

C
的成员(构造函数),所以我们在这里仍然很好

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

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

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

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

在这种情况下,对象表达式的类应为C或a类 源于C

最后,标准规定表达式的类必须是
C
或进一步的派生类。在这种情况下,表达式
Base()
实际上是一个
C
,调用父构造函数(将其视为
this->Base()
。表达式
b
的类型显然是
Base
(这是明确声明的成员
b
,想想
this->b->Base()


当在类
N
中命名时,成员
m
可在点R处访问,如果

  • m
    作为
    N
    的成员是公开的,或者

  • m
    作为
    N
    的成员是私有的,而R出现在类
    N
    的成员或朋友中,或

  • m
    作为
    N
    的成员受到保护,而R出现在类
    N
    的成员或朋友中, 或者在类的成员或朋友中
    P
    来自
    N
    ,其中
    m
    作为
    P
    的成员是公共的、私有的或受保护的,或者

  • 存在一个
    N
    的基类
    B
    ,该基类可在R处访问, 当在类
    B
    中命名时,可以在R处访问
    m

用于构造函数调用

Base b2;
上述第三点适用。
m
Base
构造函数。
N
命名类是
Base
m
,因为
Base
的成员受到保护,声明发生在派生自
Base
的类
的成员中,但
Base不是这种情况de>构造函数作为
派生的
的成员是公共的、私有的或受保护的:它不是
派生的
的成员,构造函数不是隐式继承的

我认为“是公共的、私人的或受保护的”这句话相当尴尬;我只能猜测这是这一段演变的结果

我还没有找到一个解释,说明受保护的
Base
构造函数是如何在
Derived
中的成员初始值设定项列表中访问的,但是我刚刚开始研究这个问题



更新:我在初始化列表中找不到与访问构造函数相关的标准语言,也找不到任何关于它的缺陷报告。这很可能是一个缺陷。

我看到了,但在标准中这是在哪里指定的?@Brian:你应该将该注释移到问题上。否则问题是重复的。@Cheersandhth.-Alf问题是“标准对此有何规定”,但我还是对其进行了编辑以重申。相关/重复:有趣的是,构造函数应该没有名称[class.ctor],访问控制不应该应用于它们;)(以及名称查找)@dyp,我认为OP了解这一行为。他正在标准中寻找证据,清楚地解释这一行为。你发布的链接没有任何答案指向任何相关的地方