[读书笔记] 深入探索C++对象模型-第五章-构造、析构、拷贝语义学(下)

继续整理第五章剩下的内容,关于析构函数语义的。

1. 如果类没有定义析构函数,那么只有类中含有成员对象(或者本类的基类)拥有析构函数的情况下,编译器才会合成一个出来,否则析构函数被视为不要,也就不需要合成。例如,如下类,虽然Point类拥有虚函数:

class Point {
piblic: 
    Point(float x = 0.0, float y = 0.0);
    Point (const Point&);
    virtual float z();
private:
    flaot _x, _y;
};
同样的道理,如下类也不需要合成析构函数:

class Line {
public:
    Line(const Point&, const Point&);
    virtual draw();
protected:
    Point _begin, _end;
};
当由Point类派生出(包括虚继承)Point3d类时,如果没有声明虚函数,那么编译器就不会合成一个。

之所以有上述机制,当此语句发生时:

Point *p = new Point3d;

必须调用构造函数初始化类对象,没有构造函数,抽象化的使用就会有错误的倾向。当我们delete掉一个类对象时:

delete p;

不需要在delete之前做类似的操作:

p->x(0);//x(float)和y(float)是Point类的成员函数 
p->y(0);
结束p声明之前,没有任何类使用者层面的程序操作是程序员所必需的,因此,也就不一定需要一个析构函数。

2. 对于多重继承和虚拟继承而言,情况要有所不同,当我们从Point3d和Vertex(虚拟继承自Point)派生出Vertex3d时,如果我们不声明Vertex3d的析构函数,但我们仍然希望Vertex3d对象结束时,调用Vertex的析构函数,那么编译器此时必须合成一个Vertex3d的析构函数,该函数唯一的任务就是调用Vertex的析构函数,如果我们提供一个Vertex3d的析构函数,编译器会扩展之,在我们的代码之后调用Vertex的析构函数,该扩展与构造函数的扩展类似,但是顺序相反:

    a. 析构函数本身被执行。

    b. 调用成员类对象的析构函数(如果有的话),调用顺序使他们声明的相反顺序。

    c. 重置虚表指针。

    d. 调用非虚基类的构造函数(如果有的话),调用顺序使他们声明的相反顺序。

    e. 调用虚基类的构造函数(如果有的话),如果当前类是最尾端(most-derived)的类,那么虚基类用原来构造顺序的相反顺序析构。

一个类对象生命结束于其析构函数调用开始执行之时,由于每一个基类析构函数都会被调用,所以子类实际上变成了一个完整的对象,例如:对于类d继承自c,c继承自b,b继承自a,当d对象析构时,会依次变成一个c对象,b对象,a对象,当我们在析构函数中调用成员函数时,对象的蜕变会因为虚表指针的重新设定(析构函数中,程序员所供应的代码执行之前)而受到影响,这个会在第六章的内容中整理。

第五章的内容整理到此,之后会继续第六章内容的整理。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值