为什么要将一个父类的析构函数写成一个虚函数,和内存泄漏有关,怎么理解?

今天被一个问题困扰了一下,当我们定义了一个类,然后在让一个子类去继承这个类,定义子类和父类都写好构造函数和析构函数,实例化这个子类对象时,会先调用父类的构造函数,在调用子类的构造函数,释放这个对象的时候恰恰相反 ,先调用子类析构函数,在调用父类析构函数,那么,问题就是存在这种继承机制的类是否会额外消耗很多的存储空间呢?比如说一个类,继承多个父类或者说链式继承,即他的父类还继承了别的类,那么示例化一个子类对象难道说要将他的所有父类都实例化?期待高手回答这个问题,相信还有很多人对这个不是很理解,固然大家知道不可能将所有的父类都实例化,但是,子类必然包含有父类的相关信息,是简单的复制,还是压栈式的融合,我对此表示还不清楚,因此不敢妄加评论,希望高手能解答。

 好了,继续我要说的问题,那么,如果以指针形式声明一个基类类型指针,然后调用子类构造函数为其构建对象,当释放对象的时候,是调用父类析构函数还是调用子类析构函数呢?看下面的例子;

 

[cpp]  view plain  copy
  1. // virtual.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <string.h>  
  6.   
  7. #define MAXLEN 128  
  8. class CEmployee{  
  9. public:  
  10.     int m_ID;  
  11.     char m_Name[MAXLEN];  
  12.     char m_Depart[MAXLEN];  
  13.     CEmployee(){  
  14.         printf("CEmployee 类构造函数被调用了/n");  
  15.     }  
  16.     ~CEmployee(){  
  17.         printf("CEmployee 类析构函数被调用了/n");  
  18.         getchar();  
  19.     }  
  20. protected:  
  21. private:  
  22. };  
  23. class COperator:public CEmployee{  
  24.           
  25. public:  
  26.     char m_Password[MAXLEN];  
  27.     COperator(){  
  28.         strcpy(m_Name,"MR");  
  29.         printf("COperator 子类的构造函数被调用了/n");  
  30.         getchar();  
  31.     }  
  32.     ~COperator(){  
  33.         printf("COperator 子类析构函数被调用/n");  
  34.         getchar();  
  35.     }  
  36.   
  37. };  
  38. int _tmain(int argc, _TCHAR* argv[])  
  39. {  
  40.     CEmployee *oper = new COperator() ;  
  41.     delete oper;  
  42.     return 0;  
  43. }  

函数的返回结果是:

可以看到值调用了父类的析构函数,而子类的析构函数没有被调用,那么可想而知,如果在子类的构造函数中对某个成员函数在堆空间中分配了空间,而之类没有被调用,是不是会造成内存泄漏呢?答案是肯定的,那有什么办法可以解决这种情况下出现的内存泄漏呢?那就是把父类的析构函数写为虚函数,看下面的代码:

[cpp]  view plain  copy
  1. // virtual.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <string.h>  
  6.   
  7. #define MAXLEN 128  
  8. class CEmployee{  
  9. public:  
  10.     int m_ID;  
  11.     char m_Name[MAXLEN];  
  12.     char m_Depart[MAXLEN];  
  13.     CEmployee(){  
  14.         printf("CEmployee 类构造函数被调用了/n");  
  15.     }  
  16.     virtual ~CEmployee(){  
  17.         printf("CEmployee 类析构函数被调用了/n");  
  18.         getchar();  
  19.     }  
  20. protected:  
  21. private:  
  22. };  
  23. class COperator:public CEmployee{  
  24.           
  25. public:  
  26.     char m_Password[MAXLEN];  
  27.     COperator(){  
  28.         strcpy(m_Name,"MR");  
  29.         printf("COperator 子类的构造函数被调用了/n");  
  30.         getchar();  
  31.     }  
  32.     ~COperator(){  
  33.         printf("COperator 子类析构函数被调用/n");  
  34.         getchar();  
  35.     }  
  36.   
  37. };  
  38. int _tmain(int argc, _TCHAR* argv[])  
  39. {  
  40.     CEmployee *oper = new COperator() ;  
  41.     delete oper;  
  42.     return 0;  
  43. }  

运行结果:

 

因此,在写父类的时候,最好将其析构函数写为虚函数。这样可以防止比较瘾避的内存泄漏。



转自: 为什么要将一个父类的析构函数写成一个虚函数,和内存泄漏有关,怎么理解? - 做一个道者 - 博客频道 - CSDN.NET
http://blog.csdn.net/bravekingzhang/article/details/6436366

猜你喜欢

转载自blog.csdn.net/qq_20218109/article/details/53330431