《深入探索C++对象模型》第二章 构造函数语义学(The Semantics of Constructors)
一、default constructor的构造操作
先看一个小例子:
class Foo { public: int val; Foo *pnext; };
此处正确的程序语意是要求Foo有一个默认构造函数,能将它的两个成员初始化为0,那么编译器会为我们合成这样的默认构造函数吗?答案是不会!(事实上,这里合成的默认构造函数是trival的构造函数,也就是它什么也不干,连初始化也不干。在概念上我们把这种构造函数叫做implicit trival default constructors,但实际上这种构造函数根本不会被合成出来)。这是因为初始化成员是程序的需要,而不是编译器的需要,本例中要承担成员初始化责任的是设计者。
在四种情况下,non-trival default constructor会被编译器合成出来,下面一一讨论这四种情况。
1. 带有Default constructor的Member Class Object
如果一个class没有任何constructor,但它内含一个member object,而后者有default constructor,那么编译器就需要为该class合成出一个default constructor,不过这个合成操作只有在constructor真正需要被调用时才会发生。
这就引出一个问题,在C++的各个不同的文件中,编译器如何避免合成出多个default constructor?解决办法是把合成的default constructor、copy constructor、deconstructor,copy assignment operator都以inline方式完成,一个inline函数具有静态链接,不会被文件以外者看到。如果函数太复杂不适合做成inline,就会合成出一个explicit non-inline static实例。(这一段没太明白)
下面是一个小例子:
class Foo { public: Foo(), Foo(int) ... };
class Bar { public: Foo foo; char *str; };
void foo_bar()
{
Bar bar; //Bar::foo在这里必须被初始化
if( str ) { }...
}
在本例中,编译器将为class Bar合成一个default constructor,内含必要的代码,能够调用class Foo的default constructor来处理member object Bar::foo,但是要注意,这个default constructor依然不会负责str的初始化!
未完待续...