析构函数最好都用virtual 。先解释下析构函数和指针之间的交互。以及虚构函数的具体含义。
例如下面的代码其中的SomeClass 是含有非virtual 析构函数的一个类
SomeClass *p= new SomeClass;
...
delete p;
为p调用delete时候会自动调用SomeClass类的析构函数,现在看看将析构函数极为virtual 的时候发生什么东东。
描述析构函数和虚函数机制交互时候,最简单的说法是:将所有的虚构函数都视为其相同的名称,(即使他们并非真的同名)
假如Derived类是Base类的一个派生类,并假定Base类中的析构函数标记为virtual 现在分析以下代码
Base *pBase= new Derived;
...
delete pBase;
为pBase 调用delete 时候会调用一个析构函数,由于Base类中的析构函数标记为virtual 而且指向的对象属于Derived 类型,所用会调用Derived的析构函数(它接着调用Base类的析构函数)如果Base类中的析构函数没有标记为virtual那么只会调用Base中的析构函数。要注意的另一点是将析构函数标记为vitrual 后派生类中的所有析构函数都会自动成为virtual 不管是否用virtual 这种行为就好比所有的析构函数都具有相同的名称。
现在解释为什么所有的析构函数都是virtual 的假定Base类中有一个指针类型的成员变量pB,Base类的构造函数会创建由pB指向的一个动态变量,而Base类的析构函数会删除pB指向的动态变量,另外假如Base类中的析构函数没有标记为virtual 并假定Derived 类,(它从Base派生)有一个指针类型的成员变量pD,Derived 类的构造函数会创建一个有pD指向的动态变量,而Derived类的析构函数会删除pD指向的动态变量。
Base *pBase= new Derived;
...
delete PBase;
由于基类中的析构函数没有标记为virtual 所以只会调用Base类的析构函数。这会将pB指向的动态变量占用的内存返还给自由存储,(除非程序终止)。另一方面,如果将基类中的Base的析构函数标记为virtual 那么为pBase 调用delete时会自动调用Derived 类的析构函数(因为指向的对象是Derived 类型)Derived 类的析构函数会删除pD指向的动态变量,再自动调用基类的Base析构函数,后者会删除pB指向的动态变量。
因此将基类的析构函数标记为virtual之后,所有的内存都能成功的由自由存储来回收。为了准备迎接这种情况,最好总将析构函数标记为virtual 。