当派生类对象从内存中撤销时一般先运行派生类的析构函数,然后再调用基类的析构函数。
如果用new运算符建立的派生类的临时对象,对指向基类的指针指向这个临时对象当用delete运算符撤销对象时,系统执行的是基类的析构函数,而不是派生类的析构函数,不能彻底的“清理现场”。
解决的方法是将基类及派生类的析构函数设为虚函数,这时无论基类指针指向哪个派生类对象,系统会采用动态关联,调用相应的析构函数对对象进行清理。
class
Point
{
public
:
Point(){};
~Point(){ std::cout <<
"Point destructor"
<< std::endl; }
private
:
};
class
Circle
:
public
Point
{
public
:
Circle(){};
~Circle(){ std::cout <<
"Circle destructor"
<< std::endl; };
private
:
};
int
_tmain
(
int
argc
,
_TCHAR
*
argv
[])
{
Point
*p =
new
Circle
;
delete
p;
getchar();
return
0;
}
程序运行结果如下:
下面将基类的析构函数改成虚析构函数
virtual ~Point(){ std::cout <<
"Point destructor"
<< std::endl; }
其它的不变,再运行:
这样就达到我们的目的了,基类,派生类都调用了析构函数,另外需要注意的是
在基类的析构函数声明为虚函数时,由该基类派生的析构函数也自动成为虚函数,即使派生类的析构函数与基类的析构函数名字不相同。
程序中显示的用delete运算符删除一个对象,而这个对象是指向派生类对象的基类指针,系统调用相应派生类的析构函数。
如果程序中的局部对象离开其作用域,系统会隐式地调用其析构函数
咱们增加一个函数并从写main函数:
Point
*fc()
{
Circle
cl;
Point
*p =
new
Circle
;
return
p;
}
int
_tmain
(
int
argc
,
_TCHAR
*
argv
[])
{
Point
*q = fc();
delete
q;
getchar();
return
0;
}
运行结果如下:
在上例中,函数非常fc的内部定义了两个对象:c1和p所指向的Circle类对象。对象cl在函数fc结束时执行Circle的析构函数,撤销局部变量c1.p所指向的对象的地址通过函数返回值赋予q,q所指向的对象在执行delete时执行析构函数。