1

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

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

我得到以下编译错误:

错误:在此上下文中无法访问“类 AA::A”

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

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

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

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

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

我知道的:

(1) 当我对 B & C 进行“公共虚拟继承”时,即使在大多数派生类的构造函数初始化程序列表中提到了大多数基类的默认构造函数,也会被调用。表示下面的语句编译。D() : A(), B(), C() {cout << "4";}

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

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

4

2 回答 2

0

正如评论中提到的,A()不能显式调用 fromD()因为是andA()的私有成员。继承提供了对公共和受保护成员的访问权,并使它们成为私有的。任何私人的,都不会被继承。所以关键是继承期间的访问说明符,而不是虚拟继承。您可以尝试从您的示例中删除。该程序将打印,因为虚拟继承提供了一个公共基础对象。BCprivatevirtual12134

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

于 2021-03-26T20:26:16.013 回答
0

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

于 2017-05-05T06:11:24.027 回答