#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了。
所以如果没有虚析构函数的话, 那么子类中特有的部分就不会被释放, 造成"经典"的释放一半, 泄露一半的内存泄露.