创建派生类的对象:先调用基类构造,再调用子类构造。不能把构造函数定义为虚函数。
删除派生类的对象:先调用派生类的析构函数,再调用基类的。
问题:如果是动态绑定,基类的指针所指向的派生类的对象是通过new在堆上创建的,使用delete运算删除派生类对象,则只调用了基类的析构函数,而没有调用派生类的析构函数,这样就无法完成正确的对象清理工作(正确应该是要调用派生类的析构函数)。
解决办法:把析构函数定义为虚函数。这样无论指针所指的对象是基类的还是派生类的对象,虚析构函数的使用都能保证程序调用对应(动态绑定)的析构函数。虚析构函数是常用的。
#include <iostream>
using namespace std;
class Base{
public:
Base(){cout << "Base::constructor"<<endl;}
virtual ~Base(){cout << "Base::destructor"<<endl;}
};
class Derived : public Base{
public:
Derived(){cout << "Derived::constructor"<<endl;}
virtual ~Derived(){cout << "Derived::destructor"<<endl;}
};
int main()
{
Base *pBase = new Derived;
delete pBase;
return 0;
}
输出
Base::constructor
Derived::constructor
Derived::destructor
Base::destructor
如果析构函数不是虚函数,则结果是:
Base::constructor
Derived::constructor
Base::destructor
#include <iostream>
using namespace std;
class Base{
public:
Base(){cout << "Base::constructor"<<endl;}
~Base(){cout << "Base::destructor"<<endl;}
};
class Derived : public Base{
public:
Derived(){cout << "Derived::constructor"<<endl;}
~Derived(){cout << "Derived::destructor"<<endl;}
};
int main()
{
Base *pBase = new Derived;
delete pBase;
pBase = 0;
Derived d;
pBase = &d;
return 0;
}
输出:
Base::constructor
Derived::constructor
Base::destructor
Base::constructor
Derived::constructor
Derived::destructor
Base::destructor
可见如果不是new出来的派生类对象,还是可以正确清理的。