在类层次结构中,用多态性分配对象时会出现一个问题:
如果一个对象(带有非虚拟析构函数)被delete操作符作用于指向对象的基类指针从而显式删除删除该对象,基类析构函数(与该指针类型相匹配的)仍然会被这些对象调用。不管基类指针指向哪种对象类型,不管各个类的析构函数是否相同,都会出现这个问题。
解决该问题有个简便方法:
声明一个虚拟的基类析构函数,这样就可以使所有派生类析构函数变成虚拟析构函数,即使派生类的析构函数与基类析构函数的名称不同。这样,如果用delete操作符作用于指向派生类对象的基类指针从而显式删除类层次结构的对象,就会调用合适的类的析构函数。记住,派生类对象被删除时,派生类的基类部分也会被删除-在派生类析构函数执行之后自动执行基类的析构函数。(摘自《C++编程金典》)
- #include <iostream>
- using std::cin;
- using std::cout;
- using std::endl;
- class a
- {
- public:
- a(){cout << "base class construct!" << endl;};
- ~a(){cout << "base class destruct!" << endl;};
- //virtual ~a(){cout << "base class destruct!" << endl;};
- virtual void print()=0;
- };
- class b : public a
- {
- public:
- b(){cout << "non-base class construct!" << endl;};
- ~b(){cout << "non-base class destruct!" << endl;};
- virtual void print(){cout << "i am i class b!" << endl;};
- };
- int main()
- {
- a *p=new b;
- p->print();
- delete p;
- }
- /*
- 输出:
- base class construct!
- non-base class construct!
- i am i class b!
- base class destruct!
- 如果采用虚拟析构函数将输出:
- base class construct!
- non-base class construct!
- i am i class b!
- non-base class destruct!
- base class destruct!
- */
如果类不用new生成,而是用
b test;
a *p=&test;
效果是一样的,而且类b的对象test生存期是在整个main函数内;
如果这样生成类的对象
a *p=&test();
则在下面的p->print()就会出现错误,因为&test()建立了一个临时类,而该临时类的生存期只在这句话中,也就是说在p赋值时调用类b的构造函数,赋值完成后立即调用类b的析构函数,所以当下面再应用p来操作类b的对象时就会出现错误(这里的编译器是VC 6.0,Linux下G++没有试过)。