Inside the C++ Object Model Chapter 2 : The Semantics of Constructor 构造函数语义学
一、默认构造函数 Default Constructor
C++编译器会在Class的每一个构造函数中通过添加代码的方法暗中(implicit)做了下面几件事:
- 如果在这个构造函数没有对所有Member Class Object进行构造, 编译器会调用余下没有构造的Member Class Object的默认构造函数;
- 如果此构造函数没有提供基类构造函数的参数列表, 编译器会调用基类的默认构造函数;
- 如果类中含有虚函数,编译器会利用构造函数产生一张virtual function table(vbtl),并在每个Class Object中添加一个vprt(指向vbtl的指针);
- 如果类有Virtual Base Class虚基类,编译器会在构造函数中添加代码, 允许每个虚基类的执行期存取操作。
如果这个Class没有任何构造函数, 而且发生上述四种情况的任意一种, 编译器就会生成一个默认构造函数
有以下两个误区:
- 任何Class只要没有定义default constructor,就会被合成一个来;
- 编译器合成出来的default constructor会明确设定class内每一个data member的值。
二、拷贝构造函数 Copy Constructor
拷贝构造函数的情况于默认构造函数类似。编译器对没有声明拷贝构造函数的对象实行Bitwise Copy(位逐次拷贝),也就是简单的复制类中的每一个成员,此时编译器不会生成默认拷贝构造函数。但若出现以下四种情况的任意一种,编译器将会生成一个拷贝构造函数:
- 当Class内含一个成员对象,而且这个成员对象声明有一个拷贝构造函数(无论是被设计者声明或是被编译器合成)
- 编译器会调用基类(Base Class)的拷贝构造函数构造;
- 如果类中含有虚函数, 编译器会重新设定vptr,而不是简单的拷贝其值。如果将一个对象复制同一种类对象时,复制vptr没有问题。但如果是将一个派生类对象复制给基类对象或者反之,复制vptr的值就是错误的。
- 如果类对象的继承链上有Virtual Base Class虚基类,当一个基类对象以一个派生类对象为初值的时候,需要重新设定vptr或者offset值