考虑下面的代码g和clang(正确地)抱怨(构造函数A(int))在类D中是私有的.注意,由于A是D的虚拟基类,必须在D类的mem初始化器中初始化A,最多派生类,根据C.12中的§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; }
但是,两个编译器都不用担心D的默认构造函数在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 inD
,
不,默认构造函数不是私有的.基类A是私有的,但它的默认构造函数是public.
这就是为什么它的工作原理:当在ctor-initializer中命名基类时,命名的基类必须可访问,因为访问控制适用于名称,还有一些特殊的异常,其中标准表示隐式称为函数仍然必须可访问.
当基类被隐式构造时,这些基类不被命名.它们只是默认初始化(根据12.6.2p8),默认初始化仅检查构造函数是否可访问(根据8.5p7).
您可以通过不使用基类的私有继承的名称,但通过使用全局可访问的名称来表明问题是基类的名称:: A:
D() : ::A(1),C(3) { }