`
kmplayer
  • 浏览: 497847 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

条款14:总是让base class拥有virtual destructor

 
阅读更多
先看一个例子:
class EnemyTarget
{
public:
  EnemyTarget() { ++numTargets; }
  EnemyTarget(const EnemyTarget&) { ++numTargets; }
  ~EnemyTarget() { --numTargets; }
  static size_t numberOfTargets()
  { return numTargets; }
  virtual bool destroy();                 // returns success of
                                          // attempt to destroy
                                          // EnemyTarget object
private:
  static size_t numTargets;               // object counter
};
// class statics must be defined outside the class;
// initialization is to 0 by default
size_t EnemyTarget::numTargets;

class EnemyTank: public EnemyTarget {
public:
  EnemyTank() { ++numTanks; }
  EnemyTank(const EnemyTank& rhs)
  : EnemyTarget(rhs)
  { ++numTanks; }
  ~EnemyTank() { --numTanks; }
  static size_t numberOfTanks()
  { return numTanks; }
  virtual bool destroy();
private:
  static size_t numTanks;         // object counter for tanks
};

如果你要执行:
EnemyTarget *targetPtr = new EnemyTank;
...
delete targetPtr;

1,当你企图经由一个"base class pointer"删除一个"derived class object",而此base class有一个nonvirtual destructor,结果未定义.
将destructor声明Wievirtual可以确保其行为有良好定义,在内存释放之前,EnemyTarget和EnemyTank的destructor都会被调用.

2,如果class不含有任何virtual虚拟函数,往往意味着它不会被当做base class使用,此时令其destructor为virtual通常是个坏主意.
例如:
class Point {
public:
  Point(short int xCoord, short int yCoord);
  ~Point();
private:
  short int x, y;
};
此时Point对象可以塞进一个32-bit的缓冲器,甚至可以被当做一个32-bit数值.

而要实现虚函数,对象必须夹带一些额外信息,协助决定"哪一个虚函数应该被调用".
大部分编译器是以一个虚函数表指针来呈现这份额外信息,虚函数表指针指向一个虚函数表,内容为函数指针数组.

3,总结:只有当class内含有至少一个虚拟函数时,我们才将其destructor声明为virtual.

4,对有些classes,你既希望它们是抽象的,却又没有适当的函数可选作为pure virtual function,此时可以声明一个pure virtual destructor.
如:
class AWOV
{
virtual ~AWOV() = 0;
}
不过,你必须提供一个定义式:
AWOV:~AWOV(){}
因为派生类析构时,即便AWOV是个抽象类,~AWOV()最后还是会被调用.
因此,必须提供一个函数实体.
#include<iostream>
using namespace std;

class AWOV
{
public:
	virtual ~AWOV() = 0;
};
AWOV::~AWOV(){}

class My : public AWOV
{
};

int main()
{
    My m;
    return 0;
}

否则编译无法通过:
undefined reference to `AWOV::~AWOV()'|
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics