Default Constructor的构造操作
对于class X,如果没有任何user-declared constructor, 那么会有一个default constructor被隐式(implicit)声明出来,一个被隐式声明出来的default constructor将是一个trivial consructor......
下面讨论nontrivial default constructor的4种情况。
1.带有Default Constructor的Member Class Object
如果一个class没有任何constructor,但它内含有一个member object,而后者有default constructor,那么这个class的implicit default constructor就是“nontrivial”,编译器需要为该class合成出一个default constructor。不过这个合成操作只有在constructor真正被调用时才会发生。
如果有多个class member objects都要求contructor初始化操作。C++语言要求以“member objects在class中的声明顺序“来调用各个constructors。这一点由编译器完成,它为每个constructor安插程序代码,以”member声明顺序“调用每一个member所关联的default constructors。这些代码将被安插在explicit user code之前。举个例子,假设我们有以下三个classes:
class Dopey {public: Dopey();...};
class Sneezy {public: Sneezy(int); Sneezy();...};
class Bashful {public: Bashful();...};
以及一个class Snow_White:
class Snow_White {
public:
Dopey dopey;
Sneezy sneezy;
Bashful bashful;
private:
int mumble;
};
如果Snow_White没有定义default constructor,就会有一个nontrivial constructor被合成出来,依序调用Dopey、Sneezy、Bashful的default constructors。然而如果Snow_White定义了下面这样的default constructor:
//程序员所写的default constructor
Snow_White::Snow_White(): sneezy(1024)
{
mumble = 2048;
}
它将会被扩张为:
//编译器扩张后的default constructor
Snow_White::Snow_White():sneezy(1024)
{
//插入member class object
//调用其constructor
dopey.Dopey::Dopey();
sneezy.Sneezy::Sneezy(1024);
bashful.Bashful::Bashful();
//expilict user code
mumble = 2048;
}
2."带有Default Constructor“的Base Class
类似的道理,如果没有任何constructors的class派生自一个”带有default constructor“的base class,那么这个derived class的default constructor会被视为nontrivial,并因此需要被合成出来。它将调用上一层base classes的default constructor(如果是多继承,根据他们声明的顺序)。对一个后继的class而言,这个合成的constctor和一个”被显式提供的default constructor“没有什么差异。
如果设计者提供多个constructors,但其中都没有default constructor呢?编译器会扩张现有的每一个constructors,将“用以调用所有必要之default constructors”的程序代码加进去。它不会合成一个新的default constructor,因为其他“由user所提供的constructors”存在的缘故。如果同时亦存在着“带有default constructor”的member class objects,那些default constructor也会被调用--在所有base class constructor之后。
3.“带有一个virtual Function”Class
另有两种情况,也需要合成出default constructor:
1. class声明(或继承)一个virtual function
2. class继承自一个继承串链,其中有一个或多个的virtual base classes。
假设类中还有虚函数,编译期间会发生两步扩张活动:
1. 一个virtual function table(在cfont中被称为vtbl)会被编译出来,内放class的virtual functions地址。
2. 在每个class object中,一个额外的pointer member(也就是vptr)会被编译器合成出来,内含相关之class vtbl的地址。
对于那些未声明任何constructors的classes,编译器会为它们合成一个default constructor,以便正确地初始化每一个class object的vptr
4.“带有一个virtual Base Class”的Class
总结:有4种情况,会造成“编译器必须为未声明constructor 的classes合成default constructor”。它们分别是:
“带有Default Constructor”的Member Class Object
“带有Default Constructor”的Base Class
“带有一个Virtual Function”的Class
“带有一个Virtual Base Class”的Class
C++Standard把那些合成物称为implicit nontrivial default constructors。被合成出来的constructos只能满足编译器(而非程序)的要求。它之所以完成任务,是借着“调用member object或base object的default constructor”或是“为每一个object初始化其virtual function机制或virtual base class机制”而完成的。至于没有存在那4种情况而又没有声明任何constructor的classes,我们说它们拥有的是implicit trivial default constructors,它们实际上并不会被合成出来。
在合成default constructor中,只有base class constructor和member class objects会被初始化。所有其他的nonstatic data member(如整数,整数指针、整数数组等等)都不会被初始化。这些初始化操作对程序而言或许有需要,但对编译器则非必要。如果一程序需要一个“把某指针设为0”的default constructor,那么提供它的人应该是程序员。
C++新手一般有两个常见的误解:
1. 任何class如果没有定义default constructor,就会被合成出一个来。
2.编译器合成出来的default constructor会显式设定“class内每一个data member的默认值”
如你所见没一个是真的。