究竟什么时候该用虚析构函数?
C++中明确指出,当派生类对象经由一个基类指针被删除,而此基类仅提供了non-virtual析构函数,其结果是未定义的。如果删除基类指针,则需要运行基类构造函数并清除基类的成员,如果对象实际是指向派生类类型的对象,则没有定义这种行为。实际执行是通常发生的是对象的derived成分没有被销毁,而派生类中的base class成分通常会被销毁,这就造成了一个“局部销毁”的对象,从而造成资源泄露。消除这个问题很简答:给base class一个virtual析构函数,这会保证运行适当的析构函数。
所以,如果类要作为父类的话,要定义虚析构函数。
即使class完全不带virtual函数,就要注意了,不要试图去继承它。如标准的string和标准库中的容器vector,list,set等都不带有任何的virtual函数,如果你试图写这样的代码:
class SpecialString:pulic std::string{...};
文章刚开始提到过的问题,你是不是能够避免呢?有时候你会不自觉的义正言辞的去做的。拒绝诱惑吧,毕竟C++没有提供类似于Java的final class禁止派生机制。
有时候令class带有一个pure virtual析构函数,可能会带来便利,如Meyers在《More Effective C++》中“条款33:将非尾端类设计为抽象类”曾经提到过的那样。
这样Base成为一个abstract class,当有时候你希望拥有abstract class,但是没有任何pure virtual函数怎么办?很简答:为你希望成为abstract class的那个class声明一个pure virtual析构函数吧。虽然abstract class不能被实例化,但是别忘了需要为pure virtual析构函数提供一个定义,这也只能在类外进行了:
Base::~Base(){} //pure virtual析构函数的定义
毕竟,派生类析构函数还是回调用此函数来析构其相应部分的。
最后请记住:
1) 带多态性质的基类应该声明一个virtual析构函数。如果class带有任何virtual函数,它就应该拥有一个virtual析构函数。
2) 类的设计目的如果不是作为基类使用,或者不是为了具备多态性,就不应该声明virtual析构函数。