1、c++指出,当derivedclass对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,其结果未有定义——实际执行时通常发生的是对象derived成分没被销毁。这是形成资源泄露、在调试器上浪费许多时间的绝佳途径。
消除这个问题的做法:给base class一个virtual析构函数。
2、如果class不含virtual函数,通常表示它并不意图被用做一个base class。当class不企图被当作base class,令其析构函数为virtual往往是个馊主意。
欲实现出virtual函数,对象必须携带某些信息,主要用来在运行期决定哪一个virtual函数该被调用。这份信息通常由一个vptr指针指出。为每一个对象增加vptr会增加其对象大小(vptr在32-bit计算机体系结构中占4字节)。增加了vptr不仅增加了对象大小,而且也不再和其他语言(C)内的相同声明有着一样的结构(因为其他语言的对应物没有vptr),因此也就不再可能把它传递至其他语言所写的函数,除非明确补偿vptr——那属于实现细节,因此不再具有移植性。
3、 标准string不含任何virtual函数,但有时候程序员会错误地把它当做base class:
class specialString : public std::string{
//string有个non-virtual析构函数
};
specialString *pss = new specialString(“hello”);
std::string* ps;
ps = pss;
delete ps; //未有定义!*ps的specialString资源会泄露,因为specialString析构函数没有被调用。
类似的包括STL容器如:vector,list,set等等。如果你企图继承带有“non-virtual析构函数”的class,拒绝诱惑把!
4、pure virtual函数导致abstract(抽象)class——即不能被实体化的class。当需要抽象class。但手上没有任何purevirtual函数时,可以为你希望成为抽象类的那个class声明一个pure virtual 析构函数:
class A{
public:
virtual ~A() = 0; //声明purevirtual析构函数
}
这里必须为pure virtual析构函数提供一份定义:
A::~A() { };
析构函数的运作方式:最深层派生的class其析构函数最先被调用,然后是其每一个base class的析构函数被调用。编译器会在派生类的析构函数中创建一个对基类析构函数调用的动作,所以必须定义基类的析构函数,不然连接器会发出抱怨。