C++ 构造函数和析构函数的调用顺序、虚析构函数的作用
来源:互联网 发布:网络链路测试工具 编辑:程序博客网 时间:2024/06/06 03:44
构造函数和析构函数的调用顺序
构造函数的调用顺序:
当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的构造函数,依次类推,直至到达最底层的目标派生类的构造函数为止。
析构函数的调用书序:
当删除一个对象时,首先调用该派生类的析构函数,然后调用上一层基类的析构函数,依次类推,直到到达最顶层的基类的析构函数为止。
简单的说,构造函数是“自上向下”调用,析构函数是“自下而上”调用。
演示代码如下:
#include<iostream>using namespace std;class Base{public:Base(){cout<<"创建Base基类。"<<endl;}~Base() {cout<<"删除Base基类。"<<endl;}};class Child : public Base{public:Child() {cout<<"创建Child派生类。"<<endl;}~Child() {cout<<"删除Child派生类。"<<endl;} };int main(){cout<<"*********构造函数调用顺序示例***********"<<endl;Child *C1 = new Child;cout<<"*********析构函数调用顺序示例***********"<<endl;delete C1;}运行结果如下图:
虚析构函数的作用
通过基类的指针来删除派生类的对象时,基类的析构函数应该是虚的。
原因:在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员。如果想要用基类对非继承成员进行操作,则要把基类的这个操作(函数)定义为虚函数。析构函数同样需要如此。
如果用基类的指针来删除派生类的对象,而这个基类有一个非虚的析构函数,则结果是未定义的。后果是对象的派生部分不会被销毁,然而,基类部分很可能已被销毁,这就导致产生了“部分析构”的情况,这是一个内存泄露。
可以通过如下代码来说明:
#include<iostream>using namespace std;class Base{public:Base(){cout<<"创建Base基类。"<<endl;}~Base() {cout<<"删除Base基类。"<<endl;}/*非虚析构函数*/};class Child : public Base{public:Child() {cout<<"创建Child派生类。"<<endl;}~Child() {cout<<"删除Child派生类。"<<endl;} };int main(){cout<<"*********非虚析构函数调用示例***********"<<endl;Base *C1 = new Child;delete C1;}运行结果如下,此时删除C1指针时,只调用了Base类的析构函数,没有调用Child类的析构函数。
当更改Base基类的析构函数为虚函数时,代码如下:
#include<iostream>using namespace std;class Base{public:Base(){cout<<"创建Base基类。"<<endl;}virtual ~Base() {cout<<"删除Base基类。"<<endl;}/*虚析构函数*/};class Child : public Base{public:Child() {cout<<"创建Child派生类。"<<endl;}~Child() {cout<<"删除Child派生类。"<<endl;} };int main(){cout<<"*********虚析构函数调用示例***********"<<endl;Base *C1 = new Child;delete C1;}此时运行结果如下,先调用了Child派生类的析构函数,再调用了Base基类的析构函数。
但是,一般如果不做基类的类的析构函数一般不声明为虚函数,因为虚函数的实现要求对象携带额外的信息,这些信息用于在运行时确定该对象应该调用哪一个虚函数。典型情况下,这一信息具有一种被称为 vptr(virtual table pointer,虚函数表指针)的指针的形式。vptr 指向一个被称为 vtbl(virtual table,虚函数表)的函数指针数组,每一个包含虚函数的类都关联到 vtbl。当一个对象调用了虚函数,实际的被调用函数通过下面的步骤确定:找到对象的 vptr 指向的 vtbl,然后在 vtbl 中寻找合适的函数指针。这样子会使类所占用的内存增加。
- C++ 构造函数和析构函数的调用顺序、虚析构函数的作用
- 关于构造函数和析构函数的调用顺序
- C++构造函数和析构函数的调用顺序
- C++构造函数和析构函数的调用顺序
- 析构函数和构造函数的调用顺序
- 调用构造函数和析构函数的顺序
- 构造函数和析构函数的调用顺序
- 浅谈构造函数和析构函数的调用顺序
- C++构造函数和析构函数的调用顺序
- 类的析构函数和构造函数调用顺序
- 构造函数、拷贝构造函数和析构函数的的调用时刻及调用顺序
- 构造函数、拷贝构造函数和析构函数的的调用时刻及调用顺序
- 构造函数、拷贝构造函数和析构函数的的调用时刻及调用顺序
- 构造函数、拷贝构造函数和析构函数的的调用时刻及调用顺序
- 派生类构造函数和析构函数的调用顺序(C++)
- <C++>13.构造函数和析构函数的调用顺序
- 拷贝构造,构造函数,析构函数的调用顺序
- 【c++】构造函数调用顺序的研究
- Hiero工具的利用
- Velocity经常要用到的一些方法
- Android adb中命令的运行
- 【C++再学习】【05】有关类的一些知识点整理
- PostgreSQL服务启动时报错:“FATAL: could not create lock file "/tmp/.s.PGSQL.5432.lock": Permission denied”
- C++ 构造函数和析构函数的调用顺序、虚析构函数的作用
- 开发记录
- struts2的常量(属性)配置
- 得到UUID
- 【IOS】In-App Purchases入门
- 【AppCan 开发者故事】Samlee:西北青年的移动开发梦
- Linux samba 服务器安装
- To be improved
- 【数据库教程】第二季 关系数据库