1、派生类的构造函数、析构函数默认会调用基类的构造函数、析构函数。
顺序:基类构造、派生类构造;派生类析构,基类析构。
举例:
/******************************************************************************************************
* File:Constructor&DestructorTest
* Introduction:测试构造函数、析构函数、虚构造函数与纯虚构造函数的一些特性。
* Author:CoderCong
* Date:20141013
* LastModifiedDate:20160113
*******************************************************************************************************/
#include "stdafx.h"
#include
using namespace std;
class Base
{
public:
Base()
{
cout << "Base:Constructing" << endl;
}
~Base()
{
cout << "Base: Destructing!" << endl;
}
};
class Derived:public Base
{
public:
Derived()
{
cout << "Derived:Constructing" << endl;
}
~Derived()
{
cout << "Derived: Destructing!" << endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Derived *pDerived=new Derived;
delete pDerived;
return 0;
}
2、如果你的类用作派生类的基类,最好定义其析构函数为虚函数。
好处:定义其析构函数为虚函数,可以利用动态绑定,把一个子类对象绑定到一个基类指针上时,可以自动调用基类的析构函数。从而默认地调用基类的析构函数。
举例:
同样是上边的函数,我们把_tmain函数改为这样:
Base *pBase = new Derived;
delete pBase;
同志们注意运行结果:
Base:Constructing 天哪!居然没有调用派生类的析构函数!
注意,你delete的指针是Base类的指针。而Base的析构函数不是虚函数。当然不用调用派生类的析构函数!
天真的你也许会说,这也没什么大不了的吧?
没什么大不了的?再也没有比这更大的事情了。这可能会造成一个严峻的问题:内存泄露!我们真正想删除的是一个派生类对象,而实际上只是删除了派生类对象中基类的那一部分。如果派生部分有一些需要释放的资源,如网络、内存等,那么这些资源将无法得到释放。
作为一个严谨的C++程序员,我们当然不允许这样的事情发生。我们把Base类的析构函数改为虚函数试试看:
virtual ~Base()
{
cout << "Base: Destructing!" << endl;
}
运行结果:
我们惊喜得发现,一切都正常了。
再来理一遍:
我们new一个Derived类对象,调用了Derived类的构造函数,而此构造函数又默认地调用了基类Base的析构函数;
然后,我们把这个Derived对象绑定到Base类指针pBase,这时候,这个pBase的静态类型是Base*,动态类型却是Derived*。我们删除pBase,系统跟据动态绑定,最终调用的是~Derived,而不是~Base。调用~Derived之后,系统又默认地调用了基类析构函数~Base。
就是这样。
virtual ~Base() =0;
Base::~Base(){}
程序正常运行了。说明我们的猜测是正确的。