隐式调用无法访问的虚拟基类的构造函数

Bel*_*loc 11 c++ gcc clang virtual-inheritance c++11

请考虑以下代码.g ++和clang ++都抱怨(正确地)构造函数A(int)在类中是私有的D.注意,作为A一个虚拟的基类的D,A具有在被初始化MEM-初始化类的D,最派生类,根据在C++ 11§12.6.2/ 7.查看实例.

class A {
public:
    A(int i) : x(i) { }
    A() : x(1) {}
    int x;
};

class B : private virtual A {
protected:
    B(int i) : A(i) { } };

class C : public B, private virtual A {
protected:
    C(int i) : A(i), B(i) { }
};

class D : public C {
public:
    D() : A(1), C(3) { }
};

int main() {
    D d;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我们定义构造函数如下,那么两个编译器都不会理会类的默认构造函数A也是私有的D,即编译和执行代码D.

D() : C(3) {}
Run Code Online (Sandbox Code Playgroud)

据我所知,这是错误的.

请注意,如果我们定义:两个编译器都无法正确编译:

D() : A(), C(3) {}
Run Code Online (Sandbox Code Playgroud)

小智 8

但是两个编译器都没有理会类的默认构造函数A也是私有的D,

不,该默认构造函数不是私有的.基类A是私有的,但其默认构造函数是public.

这就是它的工作原理:在ctor-initializer中命名基类时,必须可以访问命名的基类,因为访问控制适用于名称,还有一些特殊的例外,标准表示隐式调用的函数仍然必须是可访问的.

隐式构造基类时,不会命名这些基类.它们只是默认初始化(每12.6.2p8),默认初始化只检查构造函数是否可访问(每8.5p7).

您可以通过不使用基类的私有继承名称,但通过使用全局可访问的名称来判断问题是否与基类的名称有关::A:

D() : ::A(1), C(3) { }
Run Code Online (Sandbox Code Playgroud)

实例