Effective C++ T07:为多态基类声明virtual析构函数

Effective C++学习笔记总链接

改善程序与设计的55个具体做法学习笔记-每日1条


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

【技巧】

带有多态性质base class 应该声明一个virtual 析构函数。如果class带有任何virtual函数,它就应该拥有一个virtual 析构函数。

class 的设计不是作为base class使用,或不是为了具备多态性,就不该声明virtual 析构函数。


base class带有virtual 函数应该声明一个virtual析构函数

问题】:当base class(non-virtual析构函数)类型的指针指向derived class对象被删除时,实际执行时通常发生的是对象的derived成分没有被销毁。

后果】: 造成一个诡异的“局部销毁”对象,这可是形成资源泄漏败坏之数据结构、在调试器上浪费许多时间的绝佳途径。

办法】:给base class一个virtual析构函数,此后删除derived class 对象,就会销毁整个对象,包括所有的derived class成分。

virtual 函数的目的是通过base class接口处理derived class对象

virtual函数实现

欲实现出virtual函数,对象必须携带某些信息,主要用来在运行期决定哪个virtual函数该被调用

这份信息通常是由一个所谓vptr(virtual table pointer)指针指出

vptr指针指向一个由函数指针构成的数组,称为vtbl(virtual table)

每一个带有virtual函数的class 都有一个对应的vtbl

当对象调用某一个virtual函数,实际被调用的函数取决于该对象的vptr指针所指的那个vtbl,编译器在其中寻找适合的函数指针。

若class不含virtual函数,则不要声明virtual 析构函数

如果class不含virtual函数,通常表示它不是用做一个base class,令其析构函数为virtual往往是个馊主意。

后果

  1. 对象内存增加,对象内增加vptr指针内存
  2. 不再具有移植性。该对象也不再和其他语言(如C)内的相同声明有着一样的结构(其他语言没有vptr) ,因此也就不再可能把传递至其他语言所写的函数,除非明确补偿vptr。

技巧:只要当class内含至少一个virtual函数,才为它声明virtual析构函数。

不要企图继承一个标准容器(STL容器)或任何其他“带有non-virtual析构函数”的class,都会出现“局部销毁”。

pure virtual 析构函数

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

有时候你希望拥有抽象class,但没有pure virtual 函数,怎么办?

为你希望它成为抽象的那个class声明一个pure virtual析构函数

class AWOV
{
     
public:
	virtual ~AWOV() = 0; // 声明pure virtual析构函数
};

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

但必须为pure virtual 析构函数提供一份定义。
原因】:derived class析构函数最先被调用,然后调用base class析构函数。会创建一个对~AWOV的调用动作,所以必须为这个函数提供一份定义。

你可能感兴趣的:(c++,Effective,C++,学习笔记,c++,多态)