关于父类析构函数为什么要定义为虚函数

xiaoxiao2021-02-28  68

喜欢的朋友可以关注收藏一下:  http://blog.csdn.NET/qq_31201973

本文如有错误,请及时私信我。

本文解释了父类析构函数为什么要定义为虚函数的问题。

首先这篇文章要感谢群里的  @北京-Qiao 提供了原始的代码和本文的思路

@北京-Qiao 提供的代码

#include <iostream> #include <stdlib.h> using namespace std; class base { public: void fun(){cout << "base" << endl;} }; class derive:public base { public: void fun(){cout << "derive" << endl;} }; int main() { base *p= new derive; p->fun(); system("pause"); return 0; }

这个时候父类不是虚函数,输出结果:

 

//而代码父类函数变成虚函数以后 class base { public: virtual void fun(){ cout << "base" << endl; } virtual ~base() { cout << "delete base" << endl; } };

这就和上周文章代码Shape的数组存放子类对象地址无法访问子类的情况,而在父类里写个虚函数print,子类里重写后就可以访问子类的对象了,这和上面的代码是一个道理。

 

父类指针new 子类的过程是这样的

而 static_cast 在父类转换成子类的时候会保留原类型的特性,导致访问失败。数组访问print虚函数则因为多态可以访问到子类的成员,那么就引出了一个问题析构函数定义为虚函数的原因。

我们如果delete 父类型的 p 会是这个过程:

那么delete p 调用析构是只删除base p (因为p实际是栈内存,所以只free(pc)), 没删除new derive的空间.

代码如下(因为没有成员我用cout代替):

 

#include <iostream> #include <stdlib.h> using namespace std; class base { public: virtual void fun(){ cout << "base" << endl; } ~base() { cout << "delete base" << endl; } }; class derive :public base { public: void fun(){ cout << "derive" << endl; } ~derive() { cout << "delete derive" << endl; } }; int main() { base *p = new derive; p->fun(); delete p; system("pause"); _CrtDumpMemoryLeaks(); return 0; }

输出结果:

 

改成析构函数改成虚函数后会删除子类,而删除子类后,编译器会自动调用父类的析构函数,删除父类。

改成虚函数的代码:

 

class base { public: virtual void fun(){ cout << "base" << endl; } virtual ~base() { cout << "delete base" << endl; } };

输出结果:

 

 

  所以析构函数定义为虚函数是为了防止内存泄漏。

转载请注明原文地址: https://www.6miu.com/read-44463.html

最新回复(0)