CPP Object Model: Default Constructor
目录

如果没有定义任何constructor, 编译器将生成一个implicit default constructor.

但是这个implicit default constructor只会去做编译器需要做的事,不会去做多余的事情(trivial). 比如如果class的member variables都是基本类型, 那么这个default constructor将什么都不干, 不会去初始化基本类型.

implicit default constructor只会在以下几种情况下会隐式调用(nontrivial):

1. class有 "带有default constructor的member class object"

编译器为class合成inline default constructor 或explicit non-inline static default constructor. 这个合成在真正被调用时发生.

如果class A有一个或以上的member class objects, 那么class A的每一个constructor必需调用每一个member classes的default constructor. 编译器会扩张已存在的constructors, 在其中安插一些代码, 使得user code被执行之前, 先调用必要的default constructor.

CPP要求member object在class中以声明顺序调用各个constructor, 和初始化列表的顺序无关.

总结:任何类型constructor,在进入user code之前必需调用member class object 的constructor进行初始化,或在初始化列表里显式调用(可以调用任何constructor), 或由编译器隐式调用(此时只能调用default constructor).调用的顺序是member class object的声明顺序. 基本类型的member variable无需初始化.

2. class有 "带有default constructor的base class"

任何类型constructor,在进入user code之前必需调用base class的constructor进行初始化, 或在初始化列表里显式调用(可以调用任何constructor), 或由编译器隐式调用(此时只能调用default constructor).调用的顺序是base class的声明顺序.

base class的初始化在member class object之前.

3. class有 virtual function

class声明或继承一个virtual function后, 需要编译器在constructor中调整object的vptr指向class的vtbl.

pure virtual function可以被定义,且在derived class中以指定base class命名空间的形式静态调用。 唯一例外的是pure virtual destructor一定要定义,因为继承体系中的每一个class object的destructors都会被调用。

因此, 对于含有virtual function的class的任何类型constructor, 必需对vptr进行初始化, 这是由编译器隐式完成. (?在user code之前还是之后?,constructor中virtual是不起作用的) vptr的初始化在base class constructors调用之后,member initialization list之前。

4. class继承了 virtual base class

如果class派生自一个继承串链, 其中有一个或多个的virtual base class, 则需要编译器为virtual base class的共享做些操作。

因此,对于含有virtual base class的class的任何类型constructor, 必需对virtual base class的共享进行初始化,这是由编译器隐式完成。

上面所述的4条编译器的职责, 如果用户定义了constructor, 则扩展用户定义的constructor去完成, 否则隐式定义一个default constructor去完成. 如果没有上述4种情况又没有声明任何constructor的class,它的default constructor实际上并不会合成出来。

总结

Object Consturctor的初始化顺序:

  1. virtual base class constructors 按声明顺序从左到右,由深到浅调用:
  2. 如果virtual base class列于member initialzation list中,那么任何显示的参数都应传递过去。
  3. 如果没有列于list中,而class有一个default constructor,也应该调用。
  4. virtual base class的offset必须在执行期可被存取。

  5. base class constructors按声明顺序从左到右调用:

  6. 如果base class列于member initialzation list中,那么任何显示的参数都应传递过去。
  7. 如果没有列于list中,而class有一个default constructor,也应该调用。
  8. 如果base class是多重继承下的第二或后继的base class,那么this指针必须有所调整。

  9. vptr设定初值,指向class的vtbl。

  10. member initialization list中的data members以members的声明顺序构造。没有出现在list中的但有default constructor的member也会被调用。
  11. 进入user code执行。

发表评论