理解虚析构函数
Posted Redamanc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解虚析构函数相关的知识,希望对你有一定的参考价值。
虚析构函数
示例代码(普通析构)
老样子,我们先来看如下代码:
class Base
public:
Base(int data) :ma(data) cout << "Base()" << endl;
~Base() cout << "~Base()" << endl;
void show() cout << "call Base::show()" << endl;
private:
int ma;
;
class Derive :public Base
public:
Derive(int data)
:Base(data), mb(data)
cout << "Derive()" << endl;
~Derive()
cout << "~Derive()" << endl;
private:
int mb;
;
int main()
Base* pb = new Derive(10);
pb->show();
delete pb;
return 0;
存在问题
我们先来看运行结果:
发现问题了吗?
缺少了~Derive()
!也就是说,派生类的析构函数根本没有被执行!
这样一来,就会存在内存泄漏的问题。
原因分析
那么为什么不会调用派生类的析构函数呢?
原因就在于我们是用基类
的指针,指向了堆
上new出来的派生类对象
,
并且,基类的析构函数
是普通函数,在函数调用的过程中,发生了静态绑定;
也就是说,在编译时期,编译器就确定了调用析构函数的地址只有基类的析构函数;
派生类的析构函数没有机会得到执行。
修改代码(虚析构)
分析完原因之后,我们知道,调用析构函数的时候,必须发生动态绑定,否则会导致派生类的析构函数无法调用,故,修改代码如下:
class Base
public:
Base(int data) :ma(data) cout << "Base()" << endl;
virtual ~Base() cout << "~Base()" << endl;
virtual void show() cout << "call Base::show()" << endl;
private:
int ma;
;
class Derive :public Base
public:
Derive(int data)
:Base(data), mb(data)
cout << "Derive()" << endl;
~Derive()
cout << "~Derive()" << endl;
private:
int mb;
;
int main()
Base* pb = new Derive(10);
pb->show();
delete pb;
return 0;
这个时候我们再次运行程序:
这样一来,就能正确的析构派生类对象了。
相关问题
当然,关于虚析构函数还有很多相关的问题:
构造函数可以是虚函数吗?
要回答这个问题,我们需要了解虚函数
依赖什么?
首先,虚函数能够产生地址,存储在vftable中,
其次,虚函数必须依赖对象,换句话说,对象必须存在
!
因为只有对象存在,通过对象的虚函数指针vfptr,访问到只读数据区
的vftable,这样才能得到虚函数的地址。
分析到这里,我们可以得出结论:构造函数不可以是虚函数
;
因为构造函数调用的时候,还没有对象!
什么时候需要虚析构函数?
当基类的指针(引用)指向堆上new出来的派生类对象的时候
;
delete pb(基类的指针)调用析构函数的时候,必须发生动态绑定;
否则会导致派生类的析构函数无法调用。
以上是关于理解虚析构函数的主要内容,如果未能解决你的问题,请参考以下文章