1. 默认构造函数会在需要的时候被编译器产生出来,要注意字眼“需要的时候”,例如如下代码:
- class Bat{
- public:
- int val;
- Bat* pNext;
- void bat_yell();
- };
- void Bat::bat_yell()
- {
- Bat batMan;
- if(batMan.val || batMan.pNext)
- // ...do something
- // ...
- }
按照程序员的本意,在bat_yell()方法中,batMan会调用默认构造函数将val和pNext初始化为0,但是实际结果并不是这样,程序员的需要并不代表编译器需要,当然,程序员的责任也不该被比那一起所承担,归根结底说来,上述代码片段中,并不会有默认构造函数被合成。退一步讲,即便是有默认的构造函数被合成出来了,也不会将上述的数据成员初始化为0。也就是说此时的默认构造函数是trivial (无用的,不重要的),有四种情况编译器会产生nontrivial(重要的,有用的)的默认构造函数:
a. 带有默认构造函数的类成员对象:


b. 第二种情况是基类中由默认构造函数,类似于第一种情况,如果一个没有定义默认构造函数的类继承(派生)于一个带有默认构造函数的基类,那么这个子类的默认构造函数会被合成出来,在其中以按照声明顺序分别调用基类们的构造函数。如果类设计者提供了多个构造函数,但是没有默认构造函数,编译器会扩张已有的构造函数,而不会合成一个新的默认构造函数。如果此类还包含第一种情况:含有存在默认构造函数的成员类对象,那么他们的默认构造函数会在调用基类默认构造函数之后调用。
Default Constructor的构造操作
对于class X,如果没有任何user-declared constructor,那么会有一个default constructor被隐式(implicitly)声明出来...一个被隐式声明出来的default constructor将是一个trivial(浅薄而无能,没啥用的)constructor...
一个nontrivial default constructor在ARM(注释参考手册)的术语中就是编译器需要的那种,必要的话由编译器合成出来。下面4小节分别讨论nontrivial default constructor的4种情况
“带有Default Constructor”的member class object
如果一个class没有任何constructor,但它内含一个member object,而后者有default constructor,那么这个class的implicit default constructor就是“nontrivial”,编译器为该class合成出一个default constructor。不过这个合成操作只有在constructor真正需要被调用时才会发生。
举例如下:编译器会为class Bar合成一个default constructor:
class Foo{ public: Foo(), Foo(int) ...};
class Bar{ public: Foo foo; char *str; };
void foo_bar(){
Bar bar; //注意Bar::foo必须在此初始化
if(str) { } ...
}
被合成的Bar default constructor内含必要的代码,能够调用class Foo的default constructor来处理member Bar::foo,但它并不产生任何码来初始化Bar::str。将Bar::foo初始化时编译器的责任,将Bar::str初始化则是程序员的责任。
如果有多个class member objects都要求constructor初始化操作,将如何? C++语言要求以“member objects在class中的声明顺序”来调用各个constructors
“带有Default constructor”的base class
如果一个没有任何constructors的class派生自一个“带有default constructor”的base class,那么这个derived class的default constructor会被视为nontrivial,并因此需要被合成出来。它将调用上一层base classes的default constructor(根据它们的声明的顺序)。对于一个后继派生的class而言,这个合成的constructor和一个“被显式提供的default constructor”并没有差异