如何在私有虚拟继承中调用大多数基类的默认构造函数,同时创建最底层的派生类的对象。但是,当在构造函数初始化列表中提到最底层的派生类时,同样不会被调用。
#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)在虚拟继承中,虚拟基类的构造函数直接从最底层的派生类的构造函数调用。
对我来说,这可能是一个虚拟继承的概念问题。请帮助我理解这一点,并分享相关的参考资料。
从D的角度来看,A是私有的,但即使不是私有的,D尝试构造A也是不正确的。它应该只构造直接基类和实例成员对象。默认情况下,B和C都将负责A的构造。
正如注释中提到的,不能从D()
显式调用A()
,因为A()
是B
和C
的私有成员。私有
继承允许访问公共和受保护的成员并使它们私有。任何私有的东西都不会被继承。所以关键点是继承期间的访问说明符,而不是虚拟继承。您可以尝试从示例中删除虚拟
。程序将打印12134
,因为虚拟继承提供了一个公共的基本对象。
如果有人想知道为什么程序输出1234
(或12134
在非虚拟情况下),我邀请他们阅读派生类的构造顺序:https://www.learncpp.com/cpp-tutorial/order-of-construction-of-derived-classes/