提问者:小点点

为什么大多数基类(Virtual)的默认构造函数没有在私有虚拟继承中被调用,同时创建最底层的派生类对象?


如何在私有虚拟继承中调用大多数基类的默认构造函数,同时创建最底层的派生类的对象。但是,当在构造函数初始化列表中提到最底层的派生类时,同样不会被调用。

#include<iostream>
using namespace std;
class A
{
public:
     A() {cout << "1";}

};

class B: private virtual A
{
public:
    B() {cout << "2";}

};

class C: private virtual A
{
public:
   C() {cout << "3";}

};

class D: private B, private C
{
public:
    D() : A(), B(), C() {cout << "4";}
    //D()  {cout << "4";}

};

int main()
{
   D d1;
   cout << "\n";
}

我的问题:

对于下面提到的代码

D() : A(), B(), C() {cout << "4";}

我得到以下编译错误:

错误:A类A::A在此上下文中不可访问

为什么A()构造函数在这里无法访问?

另一方面,下面提到的代码被成功编译并且A()构造函数被调用。

D()  {cout << "4";}

程序的输出是:1234意味着正在调用A()构造函数。

那么,为什么在上述两种情况下调用构造函数A()的行为会发生变化呢?

我所知道的:

(1)当我做B的“公共虚拟继承”时

(2)在虚拟继承中,虚拟基类的构造函数直接从最底层的派生类的构造函数调用。

对我来说,这可能是一个虚拟继承的概念问题。请帮助我理解这一点,并分享相关的参考资料。


共2个答案

匿名用户

从D的角度来看,A是私有的,但即使不是私有的,D尝试构造A也是不正确的。它应该只构造直接基类和实例成员对象。默认情况下,B和C都将负责A的构造。

匿名用户

正如注释中提到的,不能从D()显式调用A(),因为A()BC的私有成员。私有继承允许访问公共和受保护的成员并使它们私有。任何私有的东西都不会被继承。所以关键点是继承期间的访问说明符,而不是虚拟继承。您可以尝试从示例中删除虚拟。程序将打印12134,因为虚拟继承提供了一个公共的基本对象。

如果有人想知道为什么程序输出1234(或12134在非虚拟情况下),我邀请他们阅读派生类的构造顺序:https://www.learncpp.com/cpp-tutorial/order-of-construction-of-derived-classes/