Chinaunix首页 | 论坛 | 博客
  • 博客访问: 308689
  • 博文数量: 94
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 202
  • 用 户 组: 普通用户
  • 注册时间: 2014-08-08 20:07
文章分类

全部博文(94)

文章存档

2017年(19)

2016年(30)

2015年(12)

2014年(33)

我的朋友

分类: LINUX

2017-05-11 18:40:43

当一个基类被设计为多态用途,可能被多个类继承时,有一个很容易被忽略但又可能造成灾难性错误的一点是:基类的析构函数没有声明为virtual。

首先,我们基类的析构函数声明为virtual,看看结果怎样。代码验证如下:

点击(此处)折叠或打开

  1. #include <iostream>
  2. #include <string.h>

  3. class Base {
  4. public:
  5.     Base()
  6.     {
  7.         std::cout << "Base..." << std::endl;
  8.     }
  9.     
  10.     ~Base()
  11.     {
  12.         std::cout << "~Base..." << std::endl;    
  13.     }
  14. };

  15. class A: public Base {
  16. public:
  17.     A()
  18.     {
  19.         std::cout << "A..." << std::endl;
  20.         name = new char(64);
  21.         strcpy(name, "virtual-destructor");
  22.         std::cout << "name: " << name << std::endl;
  23.     }

  24.     ~A()
  25.     {
  26.         std::cout << "~A..." << std::endl;
  27.         delete name;
  28.         name = NULL;
  29.     }

  30. private:
  31.     char *name;
  32. };

  33. int main()
  34. {
  35.     Base *pb;
  36.     A *pa;

  37.     pa = new A();
  38.     delete pa;
  39.     std::cout << ".........................................." << std::endl;
  40.     pb = new A();
  41.     delete pb;

  42.     return 0;
  43. }
结果输出:
Base...
A...
name: virtual-destructor
~A...
~Base...
..........................................
Base...
A...
name: virtual-destructor
~Base...


从输出的结果可以看到,基类指针pb指向类A新创建的对象,在释放pb时,其实只释放了基类对象的资源,而继承类A相关的资源并未被释放,这样造成了资源泄漏!

倘若我们将基类的析构函数声明为virtual,看看测试结果有何变化。

点击(此处)折叠或打开

  1. #include <iostream>
  2. #include <string.h>

  3. class Base {
  4. public:
  5.     Base()
  6.     {
  7.         std::cout << "Base..." << std::endl;
  8.     }
  9.     
  10.     virtual ~Base()
  11.     {
  12.         std::cout << "~Base..." << std::endl;    
  13.     }
  14. };

  15. class A: public Base {
  16. public:
  17.     A()
  18.     {
  19.         std::cout << "A..." << std::endl;
  20.         name = new char(64);
  21.         strcpy(name, "virtual-destructor");
  22.         std::cout << "name: " << name << std::endl;
  23.     }

  24.     ~A()
  25.     {
  26.         std::cout << "~A..." << std::endl;
  27.         delete name;
  28.         name = NULL;
  29.     }

  30. private:
  31.     char *name;
  32. };

  33. int main()
  34. {
  35.     Base *pb;
  36.     A *pa;

  37.     pa = new A();
  38.     delete pa;
  39.     std::cout << ".........................................." << std::endl;
  40.     pb = new A();
  41.     delete pb;

  42.     return 0;
  43. }
结果输出:
Base...
A...
name: virtual-destructor
~A...
~Base...
..........................................
Base...
A...
name: virtual-destructor
~A...
~Base...

可以看到,当基类的析构函数被声明为virtual后,尽管pb的类型是Base *,但delete pb的时候,安全地将所有的资源释放掉了。

当然,如果一个类不是被设计带有多态性的基类,比如标准string和STL容器,那么就不该为其声明virtual析构函数。
阅读(1170) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~