了解虚拟基类和构造函数调用
Understanding virtual base classes and constructor calls
我对虚拟基类的工作方式有点困惑。特别是,我想知道基类的构造函数是如何被调用的。我写了一个例子来理解它:
#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
的默认构造函数。
虚拟基类总是由最派生的类构造。
相关文章:
- 类型擦除的std::function与虚拟函数调用的开销
- 是否可以使用函数指针调用虚拟析构函数?
- 为什么使用存储在虚拟方法表中的地址调用虚拟函数的函数会返回垃圾?
- 禁止子函数调用父级的抽象(或虚拟)函数
- 使用回调函数从构造函数调用虚拟/派生方法的替代方法?
- 使用在堆栈上创建的对象调用虚拟函数
- 为什么构造函数的虚拟函数调用有时有效,但其他调用却无效
- 如何从派生类函数中调用虚拟函数
- 从内部类的析构函数调用虚拟函数
- 虚拟函数调用的性能作为 for 循环中的上限
- 使用范围解析运算符时,在构造函数中调用虚拟方法是否安全?
- 编译器 虚拟函数调用的优化
- C++如何抛弃函数的虚拟性并调用基本函数,而不是覆盖
- 为什么不调用虚拟基非默认构造函数,除非大多数派生基显式调用它们?
- 从C++中的虚拟析构函数调用虚拟方法
- 从普通函数调用虚拟函数
- 如果在没有限定的情况下从构造函数/析构函数调用虚拟函数,则是否会发生虚拟调度
- 从析构函数调用虚拟函数-任何解决方法
- 从析构函数调用虚拟方法-解决方法
- 正在从成员构造函数调用虚拟函数