对于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、临时性对象