so true

心怀未来,开创未来!
随笔 - 160, 文章 - 0, 评论 - 40, 引用 - 0
数据加载中……

基类的析构函数为什么要设成虚函数

#include <iostream.h>

class A
{
public:
 A(){cout<<"A()\n";}
 ~A(){cout<<"~A()\n";}
 
};

class B : public A
{
public:
 B(){cout<<"B()\n";}
 ~B(){cout<<"~B()\n";}
};

void main()
{
 A * p = new B();
 delete p ;  
}
输出结果:
A()
B()
~A()
============================================================
在基类的析构函数前添加virtual改编后的代码:
#include <iostream.h>

class A
{
public:
 A(){cout<<"A()\n";}
 virtual ~A(){cout<<"~A()\n";}
 
};

class B : public A
{
public:
 B(){cout<<"B()\n";}
 ~B(){cout<<"~B()\n";}
};

void main()
{
 A * p = new B();
 delete p ;  
}

输出结果:
A()
B()
~B()
~A()
=================================================================
如果不是在基类的析构函数前添加virtual,而是在子类的析构函数前添加virtual,则编译不会出错,但是运行会出错。如果在此基础上再把“delete p;”这句话给注释了,那依然不会运行出错,不过这就不符合变成规范了,只要是我们自己用new创建的东西,我们就必须在适当的位置显示的调用delete来删除。
=================================================================
如果再添加一个中间类,代码如下:
#include <iostream.h>
#include <windows.h>

class A
{
public:
 A(){cout<<"A()\n";}
 virtual ~A(){cout<<"~A()\n";}
};

class B : public A
{
public:
 B(){cout<<"B()\n";}
 virtual ~B(){cout<<"~B()\n";}
};

class C : public B
{
public:
 C(){cout<<"C()\n";}
 ~C(){cout<<"~C()\n";}
};

void main()
{
 A * p = new C();
 delete p ;  
}
输出结果为:
A()
B()
C()
~C()
~B()
~A()
析构函数前添加virtual,必须要在最最根上的基类的析构函数前添加,不能再B类或C类的析构函数前添加,只要A类的析构函数添加了virtual,从A类派生的类都不必在自己的析构函数前添加virtual了。
所以如果没有虚析构函数的话, 那么子类中特有的部分就不会被释放, 造成"经典"的释放一半, 泄露一半的内存泄露.

posted on 2008-02-23 19:17 so true 阅读(1783) 评论(0)  编辑  收藏 所属分类: C&C++


只有注册用户登录后才能发表评论。


网站导航: