了解虚拟基类和构造函数调用

Understanding virtual base classes and constructor calls

本文关键字:函数调用 虚拟 基类 了解      更新时间:2023-10-16

我对虚拟基类的工作方式有点困惑。特别是,我想知道基类的构造函数是如何被调用的。我写了一个例子来理解它:

#include <cstdio>
#include <string>
using std::string;
struct A{
    string s;
    A() {}
    A(string t): s(t) {}
};
struct B: virtual public A{
    B(): A("B"){}
};
struct C: virtual public A {};
struct D: public B, public C {};
struct E: public C, public B {};
struct F: public B {};
int main(){
    D d;
    printf(""%s"n",d.s.c_str());
    E e;
    printf(""%s"n",e.s.c_str());
    F f;
    printf(""%s"n",f.s.c_str());
    B b;
    printf(""%s"n",b.s.c_str());
}

哪个输出

""
""
""
"B"

我不确定前两种情况会发生什么,但至少在第三种情况下,我预计输出是"B"。所以现在我很困惑。了解如何调用A的构造函数的规则是什么?

总是只有一个构造函数调用,并且总是实例化实际的具体类。您有责任为每个派生类赋予一个构造函数,该构造函数在必要时调用基类的构造函数,就像您在B的构造函数中所做的那样。

更新:很抱歉错过了您的要点!感谢ildjarn。

但是,您的B实际上继承了A。根据标准(FIDS中的10.1.4),"对于指定为虚拟的每个不同基类,最派生的对象应包含该类型的单个基类子对象"。在您的情况下,这意味着在构造基时,类F会立即调用A的默认构造函数,而不是B的默认构造函数。

虚拟基类总是由最派生的类构造。