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

时间:2017-05-05 05:57:02

标签: c++ default-constructor virtual-inheritance ctor-initializer private-inheritance

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

#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()构造函数在这里不可访问?

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

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

该计划的输出是: 的 1234 意味着调用A()构造函数。

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

我所知道的:

(1)当我做B&amp; B的'公共虚拟继承'时C,即使它在大多数派生类的构造函数初始化列表中提到,也会调用大多数基类的默认构造函数。 以下语句编译。 D():A(),B(),C(){cout&lt;&lt; “4”;}

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

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

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

正如评论中提到的,A() 不能从 D() 显式调用,因为 A()BC 的私有成员。 private 继承允许访问公共成员和受保护成员,并使他们成为私有。无论是私有的,都不会被继承。所以关键是继承时的访问说明符,不是虚拟继承。您可以尝试从示例中删除 virtual。该程序将打印 12134,因为虚拟继承提供了一个公共基础对象。

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