C++ Annotated Reference Manual中说“default Constructor 在需要的时候被编译器产生出来”,其关键字就是“需要的时候”,是谁需要呢?创建出来干什么事呢?
class Foo {
public:
int val;
Foo *pNext;
};
void foo_bar()
{
Foo bar;
if(bar.val || bar.pnext)
// do something;
}
在这个例子中,正确的语义是要求Foo有个default Constructor,可以将它的两个members初始化为0。但这段代码并不满足ARM中说的“在需要的时候”,其差别就在于一个是程序的需要,一个是编译器的需要。如果程序有需要,那是程序员的责任;只有编译器有需要时,编译器才会产生 default Constructor。因此,这个例子中,程序员必须explicitly 创建一个Constructor,并将val和pNext初始化。
对于class X,如果没有任何user-defined constructor,那么就会有一个default Constructor被implicitly 声明出来,一个被implicitly声明出来的default Constructor将是一个trivial的Constructor。并不是所有的implicitly default Constructor都是trivial的。有四种情况下的default Constructor是nontrivial的:
- 带有 default 构造函数的 Member Class Object
如果一个class没有任何的constructor,但是它内含有一个member object,而这个成员object有默认的构造函数,那么这个类的implicit的default constructor就是nontrivial的,编译器会合成一个default 构造函数,不过这个默认构造函数仅仅在需要的时候合成
如何避免编译器的多个模块合成多个default 构造函数? 编译器是使用inline函数做的:实际上,default constructor,default destructor,assignment copy operator都是以内联的方式完成的,内联函数是静态链接的。
class Foo
{
public:
Foo(),Foo(int);
};
class Bar {
public:
Foo foo;
char * str;
};
在这个例子中,Bar中有一个类型为Foo的member,因此Bar的implicit default Constructor就是nontrivial的,在其中,需要调用Foo的default Constructor。但Bar中str并不会被初始化,引起它是程序员的责任。
- 带有 default 构造函数的 base class 基类
这跟上面的情形类似。
- 带有virtual 函数的 class [virtual函数可以是继承的或者自己声明的]
为了支持virtual function,下面两个扩张操作会在编译期间发生:
生成一个virtual function table(vtbl),其中放置class的virtual functions地址;
生成一个pointer member(vptr),内含相关的class vtbl的地址;
对于那些没有声明任何Constructor的class,编译器会为它们合成一个default Constructor,以便正确地初始化每一个class object的vptr。
- 继承自一个继承串链,其中有一个或者多个virtual base class
《看完第一章后需要补充》
两种误解
1. 任何class ,如果没有定义默认构造函数,编译器会自动创建一个
2. 编译器合成出来的default构造函数会明确的设定class内的每一个data member的默认值