注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

c++小知识18——什么情况下析构函数才需要声明成virtual  

2011-09-14 17:16:42|  分类: C++(VC)编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

c++小知识(18)——什么情况下析构函数才需要声明成virtual
我们知道,类的构造函数是不能声明成虚拟的,但析构函数一般要声明成虚拟的,这是为什么呢?看一个例子:
  
 
class BaseClass

public: 
    BaseClass(){} 
    ~BaseClass(){ cout<<"调用基类析构"<<endl;}
    //virtual ~BaseClass(){ cout<<"调用基类析构"<<endl;}
}; 
    class SonClass:public BaseClass
 { 
    public: 
        SonClass() 
        { 
            p=(char*)malloc(20); 
        } 
        ~SonClass() 
        { 
            free(p); 
            cout<<"子类析构函数"<<endl; 
        } 
    private: 
        char *p; 
    }; 
    int _tmain(int argc, _TCHAR* argv[]) 
    { 
        BaseClass*pBase=new SonClass(); 
        if (NULL == pBase) 
        { 
            cout<<"类创建失败"<<endl; 
            exit(1); 
        } 
        delete pBase; 
        return 0; 
    } 
在这里如果我们不使用虚拟的析构函数,你会发现,调用的析构函数是父类的,也就是~BaseClass()这个函数,那么,可以想见,对于子类的一些资源,内存中仍然存在,而没有被释放。不可避免的造成了内存的LEAK,那你会说,那就用virtual呗,是啊,用了这个自然就好了,结果是先调用子类的析构函数,然后再调用父类的析构函数,至为什么是这样,如果不明白还得去加强C++的学习啊。但我们要明白,啥时候儿才要这样呢?是不是所有的析构函数都要加virtual 这个关键字,把它变成虚拟函数呢(如果不明白为什么父有,子相应的函数不加virtual也变成虚拟函数,回去好好看看书)?答案当然是否定的。
大家或者都已经明白,虚拟函数的存在,产生多态是因为有一个VPTR的虚表的指针的原因,他可以动态的迟后联编,达到多态的目的。但同样,这也是要付出代价的,一个是增加了空间的支出,另外一个造成了运行的速度的变慢,想来大家都有这个体会。特别是到了高级的语言,这个更明显。

需要引起注意的是,标准库和一些库类(比如STRING)都没有提供VIRTUAL析构函数,所以继承他们的时候儿,析构是没有什么太大意义的,如果在更高级的一些语言里,会提供一些禁止继承的关键字,这样就保证不会出现我们文中一开头提到的现象。但可惜的是,在C++中是没有的。
这样我们总结一下:
1、如果只是单纯继承或者干脆没有继承,不需要声明成虚拟。
2、如果一旦有了多态的函数,那么就必须把析构函数声明成VIRTUAL

  评论这张
 
阅读(1168)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017