您的位置:首页 > 编程语言 > C语言/C++

关于C++虚析构函数

2010-11-07 00:56 363 查看
在上一篇博文《关于C++对象的自杀》末尾提到了基类的虚析构函数,于是再添一篇。



什么时候析构函数需要加个virtual来修饰呢?

当要通过指向基类的指针删除子类对象时。



Why?

这是为了保证基类和子类的析构函数都得到调用。

个人理解:因为基类类型的指针指向的是子类对象中的基类部分,如果析构函数不为虚函数,则无法调用到子类的析构函数。



如下代码:

#include <iostream>
using namespace std;
class ClsBase{
public:
	ClsBase(){ cout << "ClsBase constructor." << endl; }
	~ClsBase(){ cout << "ClsBase destructor." << endl; }
};
class ClsDerived : public ClsBase {
public:
	ClsDerived(){ cout << "ClsDerived constructor." << endl; }
	~ClsDerived(){ cout << "ClsDerived destructor." << endl; }
};
int main(){
	ClsBase *p = new ClsDerived();
	delete p;
	return 0;
}


输出为:

ClsBase constructor.
ClsDerived constructor.
ClsBase destructor.


说明了基类析构函数不为虚函数时,delete指向基类的指针时无法调用到子类的析构函数。





将基类析构函数修改为虚函数,得到如下代码:

#include <iostream>
using namespace std;
class ClsBase{
public:
	ClsBase(){ cout << "ClsBase constructor." << endl; }
	virtual ~ClsBase(){ cout << "ClsBase destructor." << endl; }
};
class ClsDerived : public ClsBase {
public:
	ClsDerived(){ cout << "ClsDerived constructor." << endl; }
	~ClsDerived(){ cout << "ClsDerived destructor." << endl; }
};
int main(){
	ClsBase *p = new ClsDerived();
	delete p;
	return 0;
}


输出为:

ClsBase constructor.
ClsDerived constructor.
ClsDerived destructor.
ClsBase destructor.


此时,子类的析构函数得到调用。





个人理解

这是因为基类中将析构函数声明为虚函数,则析构函数(的索引/指针)会被放在虚表vtbl中。

在继承过程中,vtbl属于基类部分,即基类类型的指针p可以指到的范围。

并且,析构函数的虚函数性质会在继承过程中得到保持(虽然函数名不同),于是子类的析构函数也位于虚表中,确保delete p时可以调用到子类的析构函数。

于是,析构函数自底向上得到调用了。







最后引用C++ FAQ的一个段落:

BTW, if you're interested, here are the mechanical details of
why youneed a virtual destructor when someone says delete using a Base pointerthat's pointing at a Derived object. When you say
delete p,
and theclass of p has a virtual destructor, the destructor that getsinvoked is the one associated with the type of the object
*p, notnecessarily the one associated with the type of the pointer.
This is A GoodThing. In fact, violating that rule makes your program undefined. Thetechnical term for that is, "Yuck."
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: