effective C++读书笔记--【条款07:为多态基类声明virtual析构函数】

问题

base class的指针p,指向一个derived class,如果:

  1. base class带着一个non-virtual析构函数;
  2. derived class对象经由这个base class指针被删除;

这种情况一旦发生,结局就是:

其结果未有定义----实际执行时通常发生的是对象的derived成分没有被销毁

解决办法

解铃还需系铃人,作者说冤有头债有主,即然罪魁是base class的non-virtual析构函数,要解决的话最直接的方法就是给他一个virtual析构函数就行了。

再理解virtual函数

说到这,作者的话匣子就打开了,会出现以上的问题,究其原因是码农对virtual函数的思想理解不透彻。

公理1:virtual函数的目的是允许derived class的实现得以客制化。

客制化的最大结果就是多态,一个base class的指针可以实际指向各种客制化的derived class,所以如果一个class根本不打算用来做base class进而利用多态的化,最好就是压根不要给它实现任virtual函数。给了virtual函数就必须考虑derived class的客制化和多态。

推论1:任何class只要带有virtual函数几乎确定应该也有一个virtual析构函数。

这可以理解为公理1的一个推论,即然virtual函数的目的是允许derived class的客制化,那本体必然会是一个base class,作为一个必然(基本上可以认为是必然)会生出derived class,因此为了避免出现开头所述的问题,其析构函数也必然应该是virtual的。

推论2:如果class不含virtual函数,通常表示它并不意图被用作一个base class;
当class并不企图被当作base class,令其析构函数为virtual往往是个馊主意。

这是因为一个class如果含有哪怕一个virtual函数,为了存放vptr指针,其size都会增大。

这里需要区分【条款6】中提到的Uncopyable class,Uncopyable class虽然必然是一个base class,但是其目的并不是为了客制化或者多态,因此其可以没有virtual函数,包括析构函数也不必是virtual的。

而对于目的是客制化+多态的base class,有一个更专业的称呼叫做polymorphic base class。

需要注意的坑

现在大家都应该明白了,不要去继承不带virtual析构函数的base class,如果自己写的一个类会作为base class的话,则必须给其提供virtual析构函数。但是有种特殊情况需要注意:避免去继承任何STL容器和标准string,这些东西的析构函数都是non-virtual的。

STL的string 和所有STL容器的析构函数都是non-virtual的,因此不要继承他们。

更优雅的做法

定义abstract class,该class的声明里只包含一个pure virtual析构函数,这隐含两层意思:

  1. pure virtual函数导致本体必然是个abstract class;
  2. abstract class不能被实体化,必然只能用来做为base class;

这样一来,所有的子孙derived class的析构函数都必然是virtual函数了。

需要注意,这个pure virtual 虚构函数必须要提供一个定义,因为derived class被析构时会调用这个base class的析构函数。

class AWOV {            //AWOA = "Abstract w/o Vitruals
public:
    virtual ~AWOV()=0;    //声明pure virtual析构函数
};

AWOV::~AWOV(){} //pure virtual析构函数的定义

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值