对于C++程序员而言,编译器背着我们做了太多的事情。这一节,我将要带你一起发掘编译器对于对象构造过程的干涉。
1、
Default Constructor
C++新手一般有两个常见的误解:
1) 任何class如果没有定义default constructor ,就会被合成出一个来。
2) 编译器合成出来的default constructor会明确设定类内每一个数据成员的默认值。
然而,他们没有一个是正确的。
C++ Annotated Reference Manual中提到:如果没有明确定义default constructor,“default constructor会在需要的时候被编译器产生出来”,那么什么是需要的时候?
1)一个内含member objects的class,而该member objects含有default constructor
2)一个没有任何constructors的class派生自一个带有default constructor的base class
3)class声明或者继承了一个virtual function
4)class派生自一个继承串链,其中有一个或更多的virtual base classes.
可见,由编译器产生的default constructor 并不是为程序员服务的,而是由于编译器的需要。
2、Copy Constructor
有三种情况,会以一个object的内容作为另一个class object的初值,包括:
1)明确地以一个已存在的object对另一个object做初始化操作
2)当object被当作参数交给某个函数的时候
3)当函数传回一个class object的时候(注意,这里传回的不是引用)
同样,如果没有定义
default copy constructor,那么default copy constructor
也只有在必要的时候才会由编译器产生出来。这里的必要是指当
class
不展现
bitwise copy semantics
(位逐次拷贝语意)的时候。
那么,什么情况会导致一个
class
不展现
bitwise copy semantics
呢?
1
)当
class
内含一个
member object
,而后者的
class
声明中有一个
copy constructor
的时候,不论这个
copy constructor
是否是编译器合成的。
2
)当
class
继承自一个
base class
,而后者存在有一个
copy constructor
的时候,不论这个
copy constructor
是否是编译器合成的。
3
)当
class
声明了一个或者多个
virtual functions
的时候。
4
)当
class
派生自一个继承串链,其中有一个或者多个
virtual base classes
的时候。
前两种情况,编译器必须将
member
或者
base class
里的“
copy constructor
调用操作”安插到被合成的
copy constructor
里。而对于第
3
、
4
条,情况会有点复杂。
3、Member Initialization List
为了使程序能够被顺利编译,你必须使用member initialization list:
1)当初始化一个reference member时
2)当初始化一个const member时
3)当调用一个base class的constructor,而它拥有一组参数时
4)当调用一个member class的constructor,而它拥有一组参数时
编译器会对initialization list一一处理并可能重新排序,以反映出members的声明次序,它会安插一些代码到constructor体内,并置于任何explicit user code之前。
即将推出:5、临时性对象