隐式调用不可访问的虚拟基础的构造函数 class

Implicitly calling a constructor of an inaccessible virtual base class

考虑下面的代码。 g++ 和 clang++ 都抱怨(正确地)构造函数 A(int) 在 class D 中是私有的。请注意,由于 AD 的虚拟基础 class,因此 A 必须在 mem-initializer 中初始化class D,最派生的 class,根据 C++11 中的 §12.6.2/7。参见 live example

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;
}

但是两个编译器都不会理会 class A 的默认构造函数在 D 中也是私有的,即正常编译和执行代码,如果我们如下定义 D 的构造函数:

D() : C(3) {}

据我所知,这是错误的。

请注意,如果我们定义:

,两个编译器都无法(正确)编译
D() : A(), C(3) {}

But both compilers don't bother with the fact that the default constructor for class A is also private in D,

不,默认构造函数不是私有的。基础 class A 是私有的,但它的默认构造函数是 public.

这就是它起作用的原因:在 ctor-initializer 中命名基 classes 时,命名的基 classes 必须是可访问的,因为访问控制适用于名称,以及一些特殊的例外情况,其中标准规定隐式调用的函数仍然必须是可访问的。

当基 classes 被隐式构造时,那些基 classes 不被命名。它们只是默认初始化(根据 12.6.2p8),默认初始化仅检查构造函数是否可访问(根据 8.5p7)。

您可以通过不使用基的私有继承名称 class 而是使用可全局访问的名称 ::A 来判断问题出在基的名称 class ]:

D() : ::A(1), C(3) { }

Live example