条款07:为多态基类声明virtual析构函数
请记住:
1、polymorphic(带多态性质的) base classes 应该声明一个 virtual 析构函数。如果 class 带有任何 virtual 函数,它就应该拥有一个 virtual 析构函数。
2、 classes 的设计目的如果不是作为 base classes 使用,或不是为了具备多态性,就不该声明 virtual 析构函数。 比如标准 string 和 STL 容器都不被设计作为 base classes 使用,更别提多态了。
条款08:别让异常逃离析构函数
关于异常,本人也有一篇文章专门作为总结,可以参见:http://blog.csdn.net/woxiaohahaa/article/details/51771619 (《【C/C++】异常机制》)
析构函数吐出异常是危险的,那会抛出难以驾驭的麻烦。
因为,析构函数抛出异常时:
1)如果析构函数抛出异常,则异常点之后的程序不会执行,如果析构函数在异常点之后执行了某些必要的动作比如释放某些资源,则这些动作不会执行,会造成诸如资源泄漏的问题。 [正常情况下调用析构函数抛出异常导致资源泄露]
2)通常异常发生时,C++的机制会调用已经构造对象的析构函数来释放资源,此时若析构函数本身也抛出异常,则前一个异常尚未处理,又有新的异常,会造成程序崩溃的问题。 [在发生异常的情况下调用析构函数抛出异常,会导致程序崩溃]
请记住:
1、析构函数绝对不要吐出异常。如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们(不传播)或结束程序。
2、如果客户需要对某个操作函数运行期间抛出的异常做出反应,那么 class 应该供一个普通函数(而非析构函数)执行操作。
条款09:绝不在构造和析构过程中调用virtual函数
base class 构造期间 virtual 函数绝不会下降到 derived class 阶层。非正式的说法也许比较传神:在 base class 构造期间, vritual 函数不是 virtual 函数。
如何理解呢?很容易,我们主要可以从一下两个方面理解:
1)base class 构造函数的执行更早于 derived class 的构造函数,当 base class 构造函数执行时 derived class 的成员变量尚未初始化。如果此期间调用的 virtual 函数下降至 derived classes 阶层,其必然取用 local 成员变量,而那些成员变量尚未初始化。同理对于析构函数,一旦 derived class 析构函数开始执行,对象内的 derived class 成员变量便呈现处未定义值,所以 C++ 视它们仿佛不再存在。
2)最根本的原因:在 derived class 对象的 base class 构造期间,对象的类型是 base class,而不是 derived class。对于析构函数也是如此,在进入 base class 的析构函数后,对象就成了 base class 对象了。
请记住:
1、在构造和析构期间不要调用 virtual 函数,因为这类调用从不下降至 derived class(比起当前执行构造函数和析构函数的那层)。而且它们调用的所有函数也服从这以约束。