Chapter 5 构造析构拷贝语义学
纯虚函数:
父类的纯虚函数仍然可以被定义并在子类中以静态方式调用。
对于pure virtual destructor,类的设计者必须定义它,因为每个子类析构时会以静态方式调用其每一个virtual base class和上一层的base class的destructor(如果父类本身不为自己定义析构函数,链接时就找不到这个父类的析构实现,链接错误)。总之,不要把virtual destructor声明为pure。
继承体系下的对象构造
T object;
这样的代码在T的构造函数调用时,伴随着的动作有什么:
1. 记录在member init list中的data member会被初始化。
2. 如果有data member没有出现在member init list中,但是它有一个default ctor,则该default ctor会被调用。
3. 在那之前,如果class object有vptr,则vptr需要被设定初值。
4. 在那之前,所有上一层的base class ctor都被调用。
5. 在那之前,所有virtual base class ctor必须被调用。
如下继承结构下
构造函数:
PVertex::PVertex(float x, float y, float z) : _next(0), Vertex3d(x, y, z), Point(x, y) {
if (spyOn)
cerr << "within Point3d::Point3d()" << " size: " << size() << endl;
}
会被编译器扩展为:
PVertex* PVertex::PVertex( Pvertex* this, bool __most_derived, float x, float y, float z ) {
//有条件地调用virtual base class的ctor
if ( __most_derived != false )
this->Point::Point( x, y );
//无条件地调用上一层的base class的ctor
this->Vertex3d::Vertex3d( x, y, z );
//初始化vptr
this->__vptr__PVertex = __vtbl__PVertex;
this->__vptr__Point__PVertex = __vtbl__Point__PVertex;
//显式的用户代码
if ( spyOn )
cerr << "within Point3d::Point3d()"<< " size: "
// 虚拟机制调用size()函数
<< (*this->__vptr__PVertex[ 3 ].faddr)(this)
<< endl;
return *this;
}
对象复制语义学
copy assignment operator
如下的继承情况:
classPoint3d : virtualpublicPoint {
public:
Point3d( float x = 0.0, y = 0.0, float z = 0.0 );
...
protected:
float _z;
};
编译器会为Point3d合成一个operator=(如果没有的话),合成的operator如下:
inline Point3d& Point3d::operator=( Point3d *constthis, const Point3d &p ) {
//调用base class的operator=
this->Point::operator=( p );
// memberwise copy the derived class members
_z = p._z;
return *this;
}
析构语义学 Semantics of Destructor
如果class没有定义destructor,则只有class中的member object(或者class的base class)定义了dctor时,编译器才会为class合成一个dctor。
dctor的扩展:
1. dctor函数中的user code首先执行。
2. 如果class中有member class object,而这个member class object有dctor,则这些member class objects会以声明顺序的逆序调用各自的dctor。
3. 如果object中有vptr,则需要被重新设定,指向适当的base class的vtbl。
4. 上一层的nontrivial base class的dctor会被调用。
5. 如果有任何的virtual base class有dctor,而该class是最尾端(most-derived)的class,那么它们会按照原来构造的逆序调用dctor。