Effective C++ 小笔记:条款7-12

条款7:为多态基类声明virtual析构函数

  C++明白指出,当derived class对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,其结果未有定义。事实上,derived对象被局部销毁,只有其base class部分内存被正确释放。造成资源泄漏,败坏数据结构。

  任何class只要带有virtual函数,都几乎确定应该也有一个virtual析构函数。 如果class不含virtual函数,通常表示它不意图被用作一个base class。当class不起图被当做base class,令其析构函数为virtual往往是个馊主意:析构函数占用对象空间;并且不再和其他语言(如C)有着相同的数据结构,不具有移植性。

  心得:只有当class内含有至少一个virtual函数,才为它声明virtual析构函数。

    如果你曾经企图继承一个标准容器、string、或任何其他 ”带有non-virtual析构函数“ 的class,你肯定遇到或将遇到麻烦。很不幸C++没有提供类似java的final class的机制。

  pure virtual函数导致abstract class(抽象类),也就是不能被实体化(instantiated)的class。你不能为那种类型创建对象。 

  并非所有的base class的设计目的都是为了多态用途。某些classes的设计目的是作为base classes使用,不是为了多态。如条款6的Uncopyable,它们并非被设计用来经由base class接口(指针)处理derived class对象,因此它们不需要virtual析构函数。 

小记: polymorphic(带多态性质的)base classes应该声明一个virtual析构函数。如果class带有任何virtual函数,它就应该拥有一个virtual析构函数。

 

条款8:别让异常逃离析构函数

  C++并不禁止析构函数吐出异常,但它不鼓励你这样做。析构函数吐出异常就是危险,总会带来过早结束程序或者发生不明确行为的风险。

  析构函数绝对不要吐出异常。如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们(不传播)或结束程序。

  如果客户需要对某个操作函数运行期间抛出的异常做出反应,那么class应该提供一个普通函数(而非在析构函数中)执行该操作。如果某个操作可能在失败时抛出异常,而又存在某种需要必须处理该异常,那么这个异常必须来自析构函数以外的某个函数。

 

条款9:绝不在构造和析构过程中调用virtual函数

  在构造和析构期间不要调用virtual函数,因为这类调用从不下降至derived class调用函数(比起当前执行构造函数和析构函数的那层)。因为对象很可能已经不完整。 

 

条款10:令 operater= 返回一个 reference to *this

  先看一个连锁赋值,int x, y, z; x=y=z=15。这样是正确的,赋值操作符是右结合性的。为了实现连锁赋值,赋值操作符必须返回一个reference指向操作符左侧的实参。

  注意,这只是一个协议,并无强制性要求。

 

条款11:在operator=中处理 “自我赋值”

  确保当前对象自我赋值时operator= 有良好行为。其中技术包括:1、比对 “来源对象” 和 “目标对象” 的地址;2、精心周到的语句顺序(需要临时指针);3、以及copy-and-swap,也就是用copy构造函数建立一个临时对象,之后将临时对象和*this用swap函数交换。 

 

条款12:复制对象时勿忘其每一个成分

  copying函数,包括copy构造函数和copy assignment操作符,确保复制 “对象内的所有成员变量” 及 “所有base class 成分” 。 

posted on 2010-03-06 21:33  ︶ㄣ第二名  阅读(312)  评论(0编辑  收藏  举报