搞清虚析构函数的使用场合

疑问:什么情况下必须用虚析构?

 

先看个例子:

 

#include <iostream>  
class A  
{  
public:  
    A(){};  
    ~A()  
    {  
        std::cout << "~A" << std::endl;  
    };  
private:  
    int a;  
};  
  
class B : public A  
{  
public:  
    B(){};  
    ~B()  
    {  
        std::cout << "~B" << std::endl;  
    }  
private:  
    int b;  
};  
  
int main()   
{       
    B b;       
    return 0;  
}

    

调试发现,窗口依次输出: ~B 和 ~A,也就是说,B类对象b析构的时候,先调用了B类的析构函数,然后调用了基类的析构函数。

 

如果 main 函数中的代码,替换为如下呢?

 

int main() 
{ 
    B *pb = new B(); 
    delete pb; 
    return 0; 
}

    

你会发现,还是依次输出了 ~B 和 ~A,也就是说,当使用子类指针指向子类对象的时候,析构的时候,依然会依次调用子类和基类的析构函数。

 

如果 main 函数中的代码,替换为如下呢?

 

int main() 
{ 
    A * pa = new B(); 
    delete pa; 
    return 0; 
}

 

调试发现,这份代码,只会输出 ~A, 哦,到此终于明白了,当用基类指针指向派生类对象时,如果基类析构函数不设置为 virtual 的话,则在 delete 基类指针的时候,无法成功调用子类的析构函数。这才是虚析构函数发挥作用的真正场合。

    

上述代码解决方法: 把基类 A 的析构函数设置为 virtual,则可以成功实现delete pa 的时候依次调用B类和A类的析构函数了。

    

那么,进一步讲,我们是否应该把所有类的析构函数都设置为虚析构呢?

    

不应该,这样设置不合理,只有在该类可能作为基类的情况下,并且可能使用到多态特性的时候,才有必要把基类的析构函数设置为虚析构,否则,没有必要,因为设置为虚析构会产生额外的开销,即下一个问题:

    

一个类如果把析构函数设置为 virtual 是否也会产生虚函数表?

    

我们把上述代码稍微改一下: 

 

class A  
{  
public:  
   A(){};  
   ~A()  
   {  
       std::cout << "~A" << std::endl;  
   };  
   void test() 
   { 
      std::cout << "~test" << std::endl; 
   } 
private:  
    int a;  
};  
  
int main()  
{  
    std::cout << sizeof(A) << std::endl;  
}

 

如果 ~A 前面不加 virtual 则输出的结果是: 4

如果 ~A 前面加 virtual 则输出的结果是: 8 

 

可以得出如下结论:

 

(1) 如果类没有virtual成员函数时,类的大小由数据成员大小决定

(2) 虚析构函数也会使类产生虚函数表,并且虚函数表的大小是 4 字节

 

结束语

 

免费学习更多精品课程,登录乐搏学院官网http://h.learnbo.cn/

或关注我们的官方微博微信,还有更多惊喜哦~

本文出自 “Jhuster的专栏” 博客,请务必保留此出处http://ticktick.blog.51cto.com/823160/961418

转载于:https://my.oschina.net/learnbo/blog/790323

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值