使用具有虚拟多重继承的基构造函数
Using base constructors with virtual multiple inheritance
运行下面的代码,我希望得到以下控制台输出:
B int v
D
取而代之的是,E 的构造函数调用 B 的默认构造函数,结果是:
B
D
实现正确构造的一种方法是在 E 中重新声明相同的 D 构造函数(即注释的代码部分),但我仍然希望有比这更好的解决方案。
准备运行代码,带有 -std=c++11 标志:
#include <iostream>
class A {
public:
virtual void fun() = 0;
virtual void fun2();
void fun3();
};
class B : public A {
public:
B();
B(int);
void fun();
void fun2();
};
class C : virtual public B {
public:
using B::B;
void fun();
};
class D : virtual public B {
public:
D();
D(int);
void fun();
};
class E : public C, public D {
public:
using D::D;
void fun();
};
void A::fun2() {}
void A::fun3() {}
B::B() { std::cout << "Bn"; }
B::B(int v1) { std::cout << "B int vn"; }
void B::fun() {}
void B::fun2() {}
void C::fun() {}
D::D() { std::cout << "Dn"; }
D::D(int v1) : B(v1) { std::cout << "Dn"; }
void D::fun() {}
/*E::E(int v1): D::B(v1){ std::cout <<"En";} */ void E::fun() {}
int main() {
E Eob(1);
return 0;
}
结论: 最终,定义 E 的显式构造函数,并显式调用虚拟基类 B(请参阅注释的代码段),是必要的。
正如Eljay首先正确评论的那样,我假设"使用D::D"是错误的使用。 "using"关键字永远不会重新定义 E 的构造函数,这与 D 的构造函数类似;它只是调用基类 D 的构造函数,并强制基类 D 构造。后一个事实触发了虚拟基类构造的层次结构(正如 StoryTeller 在下面回答的那样),并导致我的问题根据需要构造一个类 E 的对象。
这是一个相当常见的陷阱。首先让我说,A
的存在是一条红鲱鱼。您可以通过完全省略示例来缩短示例。
您看不到使用B(int)
的原因是由于C++标准中的两个子句。第一类 [inhctor]/8 说:
隐式定义的继承构造函数执行一组 将由用户编写的类执行的类的初始化 该类的内联构造函数,具有 mem 初始值设定项列表,其 只有 mem 初始值设定项具有命名基数的 mem-initializer-id 在 using-声明的嵌套名称说明符中表示的类 以及下面指定的表达式列表,其中 其函数体中的复合语句为空 ([class.base.init])。
这说明 c'tor 继承自D
年的E
被翻译成这样的东西:
E::E(int i) : D(i) {}
不幸的是,这是你的问题。因为在咨询 [class.base.init/10] 时:
在非委托构造函数中,初始化在 以下顺序:
- 首先,并且仅对于派生最多的类([intro.object]) 的构造函数,虚基类按以下顺序初始化 它们出现在定向的深度优先从左到右遍历上 基类的非循环图,其中"从左到右"是 派生类中基类的外观 基本说明符列表。
我们看到(强调我的)只有最派生的 c'tor 才能并且将初始化虚拟基础。最衍生的c'tor是如何做到这一点的?正如我们之前所写。它从其成员初始值设定项列表中省略虚拟基。因此,虚拟基础是默认初始化的。
如果你想把一个整数传递给B
的c'tor。你需要自己定义E
的构造函数:
E::E(int i) : B(i), D(i) {}
- 为什么C++构造函数在继承中需要默认参数?
- C++ 中的构造函数、继承、堆栈、堆、this-pointer 和段错误
- C++17 中复制构造函数的继承
- 无默认构造函数的继承
- protected是否保护基类构造函数或继承的类构造函数
- 静态对象池和构造函数的继承
- C++:构造函数在继承链中的放置位置
- 构造函数和继承函数 c++
- C++ 构造函数问题 // 继承的类
- 父级上受保护的构造函数和继承的默认构造函数不受保护
- 构造具有多重继承的类
- 复制构造函数和继承
- 关于构造函数和继承的解释
- c++中的派生类构造函数可以继承基类构造函数吗?
- 使用父类构造函数为继承的变量重新赋值
- 从未知的派生类调用接口函数(多重继承)
- 带有非默认构造函数的c++继承
- 带有默认构造函数的c++继承
- 移动构造函数和继承
- 同一类的 C++ 扩展构造函数(无继承)