从为什么要将基类的析构函数定义为虚函数谈起~~
2014-04-28 20:58
411 查看
首先,做一个最简单的实验,在电脑上运行下面的代码,将会产生运行错误,这或许会使你百思不得其解:
记得刚开始学继承的时候,似乎就被强行的记住 “基类的析构函数要是虚函数!!”,可是为什么呢?
显然,这与对象在内存中的布局方式有关。
在C++中,如果类中有虚函数,那么它就会有一个虚函数表的指针__vfptr,在类对象最开始的内存数据中。之后是类中的成员变量的内存数据。
值得注意的是,无论继承(单层)层次有多深,对象中都只有一个虚函数指针。。
也就是说,如果Derived2 继承 Derived ,最终的内存布局中也只有一个虚函数指针。
那么上述类在内存中的存在方式如下图:
显然,这可以很好的解释 析构函数 是virtual的例子了,也就是说,如果析构函数不是virtual,那么在
Base *d = new Derived();该d对象所指向的是derived的虚函数表(因为虚函数表在对象内存的起始位置),这样便可以通过Base的指针找到derived对象的析构函数,从而在
delete d ; 的时候可以释放Derived对象,不会导致内存泄露。
事实上,只需要将继承层次的最顶端的父类的析构函数设为虚函数,就可以避免上述问题,因为基类的析构函数是虚的,那么它的子类的析构函数也是虚的。
拓展:如果在基类中还存在其他的虚函数,很简单,直接将该虚函数存放在虚函数列表中,如果子类继承了改虚函数,那么只需要将子类对象的虚函数表中的函数替换为子类定义的版本即可。没有继承的,则沿用父类的版本。
#include <iostream> using namespace std; class Base { private: int a; public: ~Base(){cout << "Base dtor..." << endl;} }; class Derived : public Base { private: int b; public: ~Derived(){cout << "Derived dtor..." << endl;} }; int main() { Base *b = new Base(); Base *d = new Derived(); delete b; delete d; //这一步出现了运行时错误 return 0; }显然,这里出现了内存泄露。
记得刚开始学继承的时候,似乎就被强行的记住 “基类的析构函数要是虚函数!!”,可是为什么呢?
显然,这与对象在内存中的布局方式有关。
在C++中,如果类中有虚函数,那么它就会有一个虚函数表的指针__vfptr,在类对象最开始的内存数据中。之后是类中的成员变量的内存数据。
值得注意的是,无论继承(单层)层次有多深,对象中都只有一个虚函数指针。。
也就是说,如果Derived2 继承 Derived ,最终的内存布局中也只有一个虚函数指针。
那么上述类在内存中的存在方式如下图:
显然,这可以很好的解释 析构函数 是virtual的例子了,也就是说,如果析构函数不是virtual,那么在
Base *d = new Derived();该d对象所指向的是derived的虚函数表(因为虚函数表在对象内存的起始位置),这样便可以通过Base的指针找到derived对象的析构函数,从而在
delete d ; 的时候可以释放Derived对象,不会导致内存泄露。
事实上,只需要将继承层次的最顶端的父类的析构函数设为虚函数,就可以避免上述问题,因为基类的析构函数是虚的,那么它的子类的析构函数也是虚的。
拓展:如果在基类中还存在其他的虚函数,很简单,直接将该虚函数存放在虚函数列表中,如果子类继承了改虚函数,那么只需要将子类对象的虚函数表中的函数替换为子类定义的版本即可。没有继承的,则沿用父类的版本。
相关文章推荐
- 构造函数为什么不能为虚函数 & 基类的析构函数为什么要为虚函数
- 为什么要把父类的析构函数定义成虚函数
- 飛field(八十四)当基类同名成员函数定义为纯虚函数后,发生了什么现象?为什么会这样?
- 基类的析构函数为什么一般都是虚函数
- C/C++沉思-----多态时一定要将父类(基类)的析构函数定义为虚函数
- 多态类基类析构函数定义为虚函数原因
- C++为什么基类的析构函数是虚函数
- 为什么基类的析构函数必须为虚函数的原因-个人理解
- 析构函数为什么要定义为虚函数
- C++ 为什么设置基类的析构函数为虚函数
- C++中将基类的析构函数定义为虚函数
- 为什么析构函数要定义为虚函数
- 为什么基类的析构函数定义为虚函数
- C++ 为什么设置基类的析构函数为虚函数
- 为什么基类的析构函数是虚函数
- 【C++】基类析构函数为什么要为虚函数
- 为什么基类的析构函数定义为虚函数?
- C/C++基类的析构函数为什么要为虚函数
- 为什么基类的析构函数要声明成虚函数
- C++通过基类指针delete派生类数组,析构函数是虚函数,程序为什么会崩溃? https://www.zhihu.com/question/30838092/answer/49623765