根据上面的代码,其输出结果为:

  B1::B1()!<
  V1::V1()!<
  D1::D1()!<
  B2::B2()!<
  V2::V2()!<
  B3::B3()!<
  D2::D2()!<
  M1::M1()!<
  M2::M2()!<

  由于虚继承导致其构造顺序发生比较大的变化。不管怎么,分析的规则还是一样。

  上面分析了这么多,我们知道了虚继承有一定的好处,但是虚继承会增大占用的空间。这是因为每一次虚继承会产生一个vptr指针。空间因素在编程过程中,我们很少考虑,而构造顺序却需要小心,因此使用未构造对象的危害是相当大的。因此,我们需要小心的使用继承,更要确保在使用继承的时候保证构造顺序不会出错。下面我再着重强调一下基类的构造顺序规则:

  1、上层派生类的构造函数负责调用虚基类子对象的构造函数。所有虚基类子对象会按照深度优先、从左到右的顺序进行初始化;

  2、直接基类子对象按照它们在类定义中声明的顺序被一一构造起来;

  3、非静态成员子对象按照它们在类定义体中的声明的顺序被一一构造起来;

  4、上层派生类的构造函数体被执行。