欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

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

发布时间:2024/9/21 编程问答 54 豆豆
生活随笔 收集整理的这篇文章主要介绍了 搞清虚析构函数的使用场合 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

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


先看个例子:


#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 字节


本文转自 Jhuster 51CTO博客,原文链接:http://blog.51cto.com/ticktick/961418,如需转载请自行联系原作者

总结

以上是生活随笔为你收集整理的搞清虚析构函数的使用场合的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。