运行下面的代码我希望获得以下控制台输出:
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 << "B\n"; }
B::B(int v1) { std::cout << "B int v\n"; }
void B::fun() {}
void B::fun2() {}
void C::fun() {}
D::D() { std::cout << "D\n"; }
D::D(int v1) : B(v1) { std::cout << "D\n"; }
void D::fun() {}
/*E::E(int v1): D::B(v1){ std::cout <<"E\n";} */ void E::fun() {}
int main() {
E Eob(1);
return 0;
}
结论: 最终,需要为 E 定义显式构造函数,并显式调用虚拟基类 B(请参阅注释代码)。
正如 Eljay 首先正确评论的那样,我假设错误地使用了“using D::D”。 “using”关键字从不重新定义 E 的构造函数,这与 D 的构造函数类似;它只是调用基类D的构造函数,并强制构造基类D。后一个事实触发了虚拟基类构造的层次结构(正如 StoryTeller 在下面回复的那样)并导致我的问题根据需要构造 E 类的对象。
最佳答案
这是一个相当普遍的陷阱。首先让我说 A
的存在是一个转移注意力的问题。您可以通过完全省略示例来缩短示例。
您没有看到使用 B(int)
的原因是 C++ 标准中的两个子句。第一[class.inhctor]/8说:
An implicitly-defined inheriting constructor performs the set of initializations of the class that would be performed by a user-written inline constructor for that class with a mem-initializer-list whose only mem-initializer has a mem-initializer-id that names the base class denoted in the nested-name-specifier of the using-declaration and an expression-list as specified below, and where the compound-statement in its function body is empty ([class.base.init]).
也就是说,从 E
中的 D
继承的 c'tor 被翻译成这样:
E::E(int i) : D(i) {}
不幸的是,这是你的问题。因为经咨询[class.base.init/10] :
In a non-delegating constructor, initialization proceeds in the following order:
- First, and only for the constructor of the most derived class ([intro.object]), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
我们看到(强调我的)只有最派生的 c'tor 能够并且将会初始化虚拟基。派生最多的 c'tor 是如何做到这一点的?正如我们之前所写。它从其成员初始值设定项列表中省略了虚拟基础。所以虚拟基是默认初始化的。
如果你想传递一个整数给B
的c'tor。你需要自己定义E
的构造函数:
E::E(int i) : B(i), D(i) {}
关于c++ - 使用具有虚拟多重继承的基本构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47980682/