当前课程知识点:C++语言程序设计进阶 > 第七章 继承与派生 > 派生类的构造和析构 > 派生类的析构函数
析构函数不被继承,派生类如果需要,要自行声明析构函数。
声明方法与无继承关系时类的析构函数相同。
不需要显式地调用基类的析构函数,系统会自动隐式调用。
先执行派生类析构函数的函数体,再调用基类的析构函数。
#include <iostream> using namespace std; class Base1 { public: Base1(int i) { cout << "Constructing Base1 " << i << endl; } ~Base1() { cout << "Destructing Base1" << endl; } }; class Base2 { public: Base2(int j) { cout << "Constructing Base2 " << j << endl; } ~Base2() { cout << "Destructing Base2" << endl; } }; class Base3 { public: Base3() { cout << "Constructing Base3 *" << endl; } ~Base3() { cout << "Destructing Base3" << endl; } }; class Derived: public Base2, public Base1, public Base3 { public: Derived(int a, int b, int c, int d): Base1(a), member2(d), member1(c), Base2(b) { } private: Base1 member1; Base2 member2; Base3 member3; }; int main() { Derived obj(1, 2, 3, 4); return 0; }
大家好
欢迎回来继续学习
C++语言程序设计
这一节呢
我们来学习
派生类的析构函数怎么写
析构函数呢
它比构造函数要简单一些
因为毕竟析构函数不需要参数
析构函数跟构造函数一样
它是不被继承的
派生类如果需要的话呢
就需要定义自己的析构函数
那么由于析构函数
它没有参数
所以呢
声明析构函数的方法呢
与没有继承关系的时候
一般在类的析构函数
它的写法是一样的
而且在派生类的析构函数中
是不需要显示地
调用基类的析构函数的
但是大家应该清楚
在你去执行派生类对象
析构的时候
系统是会自动地隐式调用
基类的析构函数的
但是呢
这就跟构造的次序相反了
构造的时候是先构造
先初始化
从基类继承过来的成员
然后执行本类成员的初始化
而析构的时候呢
是先执行本类析构函数的函数体
然后再去调用
它基类的析构函数
下面呢
我们通过例题来观察一下
派生类对象的析构
现在我们在
前一个例题的基础之上
为每个类增加了析构函数
Base1 Base2的 Base3的
都增加了析构函数
那么派生类也是组合类
Derived 它的对象
在消亡的时候
是要进行析构的
析构的过程是什么呢
这些对象
成员对象所属类的析构函数
基类的析构函数
它的调用次序又是什么呢
现在我们通过运行结果
来观察一下
这个呢
我们直接在程序结束的地方
设个断点
然后按f5就直接执行到这儿
我们来看
析构函数是怎么被调用的
我们看一个输出窗口
对比一下
析构函数执行的时候呢
是首先析构本类自己的成员
然后再析构
从基类继承过来的成员
它跟构造的次序是相反的
我们看这是构造函数的执行次序
上半部是构造函数的执行次序
那么再看析构函数
执行次序是什么
构造函数执行呢
是先执行它基类的构造函数
执行次序呢
是按照它继承时的次序
然后执行对象成员的构造函数
执行的次序
也是按照它定义时的次序
那么现在看析构的时候
是什么样的
我们看到析构呢
先执行了Base3的析构函数
实际上呢
它是析构这个对象成员Base3
析构它
它是在这个对象成员中
是最后被构造的
所以最先被析构
接下来要调用Base2的析构函数
是析构这个member2这个成员
它是倒数第二个被构造的
所以它第二个被析构
然后再析构第一个
Base1类型对象 member1
那么调用Base1的析构函数
好 到此为止呢
本类的对象被析构完了
该需要析构从基类继承的对象了
从基类继承的那些成员了
那么从基类继承的成员
当然调用基类的析构函数
去析构它
这个调用次序呢
是与构造的时候的次序相反
我们看构造时候的次序呢
是依照继承时的次序自左向右
那么调用析构函数的时候
就按照继承时的次序
自右向左了
这个时候先调用
Base3的析构函数
我们看到在这儿
再调用Base1的析构函数在这儿
再调用Base2的析构函数
这就是在析构一个组合类对象
组合
还有继承都有的这个对象的时候
它们的析构次序
我们通过这个例子
就观察到了
-导学
--导学
-继承的基本概念和语法
-第七章 继承与派生--继承的基本概念和语法习题
-继承方式
-第七章 继承与派生--继承方式
-基类与派生类类型转换
-第七章 继承与派生--基类与派生类类型转换
-派生类的构造和析构
--派生类的构造函数
--派生类的析构函数
--第七章 继承与派生--派生类的构造和析构
-派生类成员的标识与访问
--虚基类
-第七章 继承与派生--派生类成员的标识与访问
-小结
--小结
-综合实例
--第七章综合实例
-实验七
--实验七
-导学
--导学
-第八章 多态性--导学
-运算符重载
--运算符重载的规则
-第八章 多态性--运算符重载
-虚函数
--虚函数
--虚析构函数
--虚表与动态绑定
-第八章 多态性--虚函数
-抽象类
--抽象类
--第八章 多态性--抽象类
-override与final
-第八章 多态性--override与final
-小结
--第八章小结
-综合实例
--第八章综合实例
-实验八
--实验八
- 第八章讲义
-导学
--导学
-模板
--函数模板
--类模板
-第九章 模板与群体数据--模板
-线性群体
--线性群体的概念
-第九章 模板与群体数据--线性群体
-数组
--数组类模板
-链表
--链表类模板
-第九章 模板与群体数据--链表
-栈
--栈类模板
--栈类模板课后习题
--例9-9 栈的应用课后习题
-队列
--队列类模板
-第九章 模板与群体数据--队列
-排序
--排序概述
--插入排序
--选择排序
--交换排序
-第九章 模板与群体数据--排序
-查找
--查找
--查找课后习题
-小结
--小结
-综合实例
--综合实例
-实验九
--实验九
- 第九章讲义
-导学
--导学
-泛型程序设计及STL的结构
--STL简介
-第十章 泛型程序设计与C++标准模板库--泛型程序设计及STL的结构
-迭代器
--迭代器
-第十章 泛型程序设计与C++标准模板库--迭代器
-容器的基本功能与分类
-第十章 泛型程序设计与C++标准模板库--容器的基本功能与分类
-顺序容器
--顺序容器的特征
--第十章 泛型程序设计与C++标准模板库--顺序容器
-关联容器
--集合
--映射
-第十章 泛型程序设计与C++标准模板库--关联容器
-函数对象
--函数对象
--函数适配器
-算法
--算法
-小结
--第十章小结
-综合实例
--综合实例
-实验十
--实验十
- 第十章讲义
-导学
--导学
-I/O流的概念及流类库结构
-第十一章 流类库与输入/输出--I/O流的概念及流类库结构
-输出流
--输出流概述
--向文本文件输出
--向二进制文件输出
--向字符串输出
-第十一章 流类库与输入/输出--输出流
-输入流
--输入流概述
--输入流应用举例
--从字符串输入
-第十一章 流类库与输入/输出--输入流
-输入/输出流
--输入/输出流
-第十一章 流类库与输入/输出--输入/输出流
-小结
--小结
-综合实例
--综合实例
-实验十一
--实验十一
- 第十一章讲义
-导学
--第12章导学
-异常处理的思想与程序实现
-第十二章 异常处理--异常处理的思想与程序实现
-异常处理中的构造与析构
-第十二章 异常处理--异常处理中的构造与析构
-标准程序库异常处理
-第十二章 异常处理--标准程序库异常处理
-小结
--第12章小结
-综合实例
--综合实例
-实验十二
--实验十二
- 第十二章讲义