benxintuzi

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

C++明确指出:当派生类对象是由一个基类指针释放的,而基类中的析构函数不是虚函数,那么结果是未定义的。其实我们执行时其结果就是:只调用最上层基类的析构函数,派生类及其中间基类的析构函数得不到调用。

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class TimeKeeper
 6 {
 7 public:
 8     TimeKeeper();
 9     ~TimeKeeper();
10 };
11 TimeKeeper::TimeKeeper()
12 {
13     cout << "Construct TimeKeeper" << endl;
14 }
15 TimeKeeper::~TimeKeeper()
16 {
17     cout << "Destruct TimeKeeper" << endl;
18 }
19 
20 class WristWatch : public TimeKeeper
21 {
22 public:
23     WristWatch();
24     ~WristWatch();
25 };
26 WristWatch::WristWatch()
27 {
28     cout << "Construct WristWatch" << endl;
29 }
30 WristWatch::~WristWatch()
31 {
32     cout << "Destruct WristWatch" << endl;
33 }
34 
35 int main()
36 {
37     TimeKeeper* pt = new WristWatch;
38     delete pt;      // 仅调用TimeKeeper::~TimeKeeper
39 
40     return 0;
41 }

现在我们将基类的析构函数变为虚析构,代码只改动一行,在~TimeKeeper()前面加上virtual,那么用基类指针释放派生类对象时,就会先调用WristWatch::~WristWatch,然后调用TimeKeeper::~TimeKeeper。

 

注意:

1> 如果在定义一个类时可以确保该类不会作为多态的基类,那么不要为其定义虚析构函数。因为虚函数的实现机制会增大对象的空间(必须保存一个指向vtable的vptr指针,会占用32bit或者64bit的存储空间)。因此,经验是:只有当一个class中至少含有一个virtual函数,才为其定义virtual析构函数。

2> 不要从non-virtual析构函数的类型继承。

 

有时候让一个类带有pure virtual析构函数更便利一些:

1 class Base
2 {
3 public:
4     virtual ~Base() = 0;    // pure virtual destructor
5 };
6 Base::~Base()               // definition
7 {
8     
9 }

主要有两方面的好处:

1> 你想拥有一个抽象类(接口),但还没找到任何有用的virtual函数可供使用

2> 同时解决了多态的析构调用问题。

但此时你必须注意:必须为这个pure virtual析构函数提供一个实现。因为在析构过程中,编译器会在派生类的析构函数中调用基类的析构函数,如果没定义,则必然发生错误。

 

总结:

  • 多态基类必须声明一个virtual析构函数。
  • 如果一个类中至少有一个virtual函数,说明该类的目的是作为多态基类存在,它就必须拥有一个virtual析构函数。
  • 如果设计一个类的目的不是作为基类使用,或者是基类但不具有多态性,那么不要声明virtual析构函数。

 

posted on 2015-05-24 15:22  benxintuzi  阅读(283)  评论(0编辑  收藏  举报