class A: public B, public C { };
在这种情况下,执行顺序为:
B(); // base(first)
C(); // base(second)
A(); // derived
class A: public B, virtual public C { };
但是在这种情况下,当我继承时使用类c写虚拟,
的顺序// execution becomes:
C(); // virtual base
B(); // ordinary base
A(); // derived
我已经读过某个地方,调用构造函数的顺序依赖于继承多个类的声明顺序,但是如何在用类编写虚拟时更改执行顺序。我无法理解为什么我得到这样的结果
答案 0 :(得分:5)
始终根据C ++标准首先执行虚拟基类构造函数。从工作草案N3242,第272页第10行,我们了解到:
因此,您看到的行为正是C ++标准所要求的。这是有道理的,因为虚拟基类可能在继承中出现多次,当然它们每个只能构造一次。因此必须有一个初始的虚拟基类构造,然后是通常的非虚基类构造。
this page还有一个很好的解释。
答案 1 :(得分:1)
如果您将虚拟类作为父类,则无法希望初始化始终按声明顺序进行。实际上,第一个(比如说非虚拟的)父类可能本身依赖于虚拟类。因此,在这种情况下,必须首先构造虚拟类。
我认为这就是为什么C ++规范说虚拟父类的初始化器总是先执行的原因。正如@Dan Roche所示,有一个可预测的初始化顺序。
示例:
class B: public A {...}
class C: public B, virtual A {...}
在C的初始化示例中,由于B的初始化需要首先初始化A,因此无法在A之前初始化B.
另一个例子 这个例子表明你不应该依赖基类初始化顺序:
#include <iostream>
using namespace std;
struct A {
A() {cout<<"A()"<<endl;}
};
struct B {
B() {cout<<"B()"<<endl;}
};
struct C: virtual A, virtual B {
C() {cout<<"C()"<<endl;}
};
struct D: virtual B, virtual A, C {
D() {cout<<"D()"<<endl;}
};
int main() {
cout<<"construct C"<<endl;
new C;
cout<<"construct D"<<endl;
new D;
}
输出:
construct C
A()
B()
C()
construct D
B()
A()
C()
D()
如示例所示,当C被构造为D的基类时,A和B的初始化顺序相反。这意味着如果您希望某人可以扩展您的类,则不能依赖虚拟基类的初始化顺序。