虚拟基类和继承

Virtual base class and inheritance

本文关键字:继承 基类 虚拟      更新时间:2023-10-16

滚动浏览SO时,我发现了这个问题

#include <iostream>
using namespace std;
class base
{
public:
base()
{
cout << "ctor in base classn";
}
};
class derived1 : public base
{
public:
derived1()
{
cout <<"ctor in derived classn";
}
};
int main()
{
derived1 d1obj;
return 0;
}

有这个问题:- 创建 d1obj 时,控件首先到达基类构造函数,然后转到派生类构造函数?还是相反:它首先到达派生类构造函数,发现它有基类,因此控件转到基类中的构造函数?

并且阿斯维尔包含该部分

当类具有虚拟基时,构造函数通常会导致发出两个不同的函数体 - 一个用于此类是派生最多的类型,另一个用于此类本身是基类时使用。原因是虚拟基类是由派生最多的类构造的,以确保它们在共享时只构造一次。因此,构造函数的第一个版本将调用所有基类构造函数,而第二个版本将仅调用非虚拟基的构造函数。

谁能用一个例子向我解释这一点?

这是该问题的链接

在您的示例中,它是负责调用base的默认构造函数的derived1的默认构造函数。但是,仅当derived1是实际(派生最多)的对象时才需要这样做,如您的示例所示

int main()
{
derived1 d1obj; // Most derived object of type `derived1`
// It contains a direct `base` subobject
// Constructor of `derived1` must construct `base` subobject as well
} 

但是当使用derived1时,它是较大对象的基本子对象

class derived2 : public derived1
{
public:
derived2()
{
cout <<"ctor in derived 2 classn";
}    
};
int main()
{
derived2 d2obj; // Most derived object of type `derived2`
// It contains a direct `derived1` subobject and an indirect `base` subobject 
// (through `derived1`)
// Constructor of `derived2` must directly construct both `derived1` subobject and 
// `base` subobject 
// Which means that constructor of `derived1` subobject should not attempt
// to construct `base` subobject
}

然后是derived2的构造函数负责调用derived1的默认构造函数和默认构造函数base。在这种情况下,derived1的默认构造函数不应调用base的构造函数,因为这会导致base的双重构造。

为了满足所有这些要求derived1通常会有两个版本的默认构造函数:在原始示例中调用的完整版本和在上面的示例中从derived2调用的"缩减"版本。

或者,derived1的默认构造函数可以用一个隐藏的布尔参数来实现,这将告诉它是否调用base的默认解释器。

"当一个类具有虚拟基数时,构造函数通常会导致发出两个不同的函数体 - 一个用于此类是派生最多的类型,另一个用于此类本身是基类时使用。原因是虚拟基类是由派生最多的类构造的,以确保它们在共享时只构造一次。因此,构造函数的第一个版本将调用所有基类构造函数,而第二个版本将仅调用非虚拟基的构造函数。

在这一点上,回答者实际上想说一种在多重继承中被称为可怕钻石C++常见的情况。 要了解,只需查看此链接的最赞成的答案 在C++中,什么是虚拟基类?