C++中确定基类有虚析构函数

  有时,一个类想跟踪它有多少个对象存在。一个简单的方法是创建一个静态类成员来统计对象的个数。这个成员被初始化为0,在构造函数里加1,析构函数里减1。(条款m26里说明了如何把这种方法封装起来以便很容易地添加到任何类中,“my article on counting objects”提供了对这个技术的另外一些改进)

  设想在一个军事应用程序里,有一个表示敌人目标的类:

  class enemytarget {

  public:

  enemytarget() { ++numtargets; }

  enemytarget(const enemytarget&) { ++numtargets; }

  ~enemytarget() { --numtargets; }

  static size_t numberoftargets()

  { return numtargets; }

  virtual bool destroy(); // 摧毁enemytarget对象后

  // 返回成功

  private:

  static size_t numtargets; // 对象计数器

  };

  // 类的静态成员要在类外定义;

  // 缺省初始化为0

  size_t enemytarget::numtargets;

  这个类不会为你赢得一份政府防御合同,它离国防部的要求相差太远了,但它足以满足我们这儿说明问题的需要。

  敌人的坦克是一种特殊的敌人目标,所以会很自然地想到将它抽象为一个以公有继承方式从enemytarget派生出来的类(参见条款35及m33)。因为不但要关心敌人目标的总数,也要关心敌人坦克的总数,所以和基类一样,在派生类里也采用了上面提到的同样的技巧:

  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:rh5n.info;

  haowe.info;

  xn567.info;

  sjkyt.info;

  u6776.info;

  w3399.info;

  fgop9.info;

  24564.info;

  557766.info;

  sfgrh.info;

  qegd.info;

  vdes.info;

  nsdr.info;

  rfdr.info;

  dcw2.info;

  khft.info;

  dhte.info;

  46fgd.info;

  59fds.info;

  bfde3.info;

  hgfr3.info;

  www.gsfea.info;

  www.swzsa.info;

  www.123wb.info;

  www.ts235.info;

  www.dt098.info;

  www.sbr69.info;

  www.xdfth.info;

  www.dft2.info;

  www.dvny6.info;

  www.rh5n.info;

  www.haowe.info;

  www.xn567.info;

  www.sjkyt.info;

  www.u6776.info;

  www.w3399.info;

  www.fgop9.info;

  www.24564.info;

  www.557766.info;

  www.sfgrh.info;

  www.qegd.info;

  www.vdes.info;

  www.nsdr.info;

  www.rfdr.info;

  www.dcw2.info;

  www.khft.info;

  www.dhte.info;

  www.46fgd.info;

  www.59fds.info;

  www.bfde3.info;

  www.hgfr3.info;

  static size_t numtanks; // 坦克对象计数器

  };

  (写完以上两个类的代码后,你就更能够理解条款m26对这个问题的通用解决方案了。)

  最后,假设程序的其他某处用new动态创建了一个enemytank对象,然后用delete删除掉:

  enemytarget *targetptr = new enemytank;

  ...

  delete targetptr;

  到此为止所做的一切好象都很正常:两个类在析构函数里都对构造函数所做的操作进行了清除;应用程序也显然没有错误,用new生成的对象在最后也用delete删除了。然而这里却有很大的问题。程序的行为是不可预测的——无法知道将会发生什么。

  c++语言标准关于这个问题的阐述非常清楚:当通过基类的指针去删除派生类的对象,而基类又没有虚析构函数时,结果将是不可确定的。这意味着编译器生成的代码将会做任何它喜欢的事:重新格式化你的硬盘,给你的老板发电子邮件,把你的程序源代码传真给你的对手,无论什么事都可能发生。(实际运行时经常发生的是,派生类的析构函数永远不会被调用。在本例中,这意味着当targetptr 删除时,enemytank的数量值不会改变,那么,敌人坦克的数量就是错的,这对需要高度依赖精确信息的部队来说,会造成什么后果?)

  为了避免这个问题,只需要使enemytarget的析构函数为virtual。声明析构函数为虚就会带来你所希望的运行良好的行为:对象内存释放时,enemytank和enemytarget的析构函数都会被调用。

  和绝大部分基类一样,现在enemytarget类包含一个虚函数。虚函数的目的是让派生类去定制自己的行为(见条款36),所以几乎所有的基类都包含虚函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值