多态是面向对象的一个基本属性,包括静态多态(编译阶段)和动态多态(运行阶段)
静态多态主要是指函数参数不同产生的多态性,是在编译阶段可以识别的一种多态机制,而运行时多态则主要用于基类指针指向派生类对象时,可以通过基类指针直接调用派生类的对象函数,当然这种多态是通过虚函数实现的。
虚函数的目的就是通知系统在函数调用时能够自动识别对应的类对象类型,从而能够根据指针所指类型调用对应的类对象,实现函数调用时的多态性。对于析构函数而言,同样适用于上述规则。如果析构函数不是虚函数,那么在调用该函数时(对象被删除时)则只会调用当前对象对应的类的析构函数,这对于直接定义的对象是没有什么影响的,但是对于使用基类指向派生类的指针而言,因为基类指针实际上是基类类型,所以析构时自然只会调用基类的析构函数,这就可能产生内存泄漏(因为派生类的析构函数不被调用)。所以如果确定程序中有基类指针指向派生类的问题,则必须将基类的析构函数指定为虚函数,如此才能确保NEW出来的对象被正确的DELETE。
示例:
#include <iostream>
using namespace std;
class Rocket
{
public:
virtual ~Rocket() //加了virtual,讲析构函数声明为虚函数
{
cout << "Rocket::~Rocket()" << endl;
}
};
class Falcon9 : public Rocket
{
public:
~Falcon9() // virtual可加可不加
{
cout << "Falcon9::~Falcon9()" << endl;
}
};
int main()
{
Rocket *pt1 = new Rocket;
Rocket *pt2 = new Falcon9; // 用基类的指针指向子类
// Falcon9 *pt3 = new Rocket; // 不能用子类指针指向基类,错误!
Falcon9 *pt4 = new Falcon9;
delete pt1;
cout << "*********" << endl;
delete pt2;
cout << "*********" << endl;
//delete pt3;
//cout << "*********" << endl;
delete pt4;
cout << "*********" << endl;
return 0;
}运行结果:
Rocket::~Rocket()
***********
Falcon9::~Falcon9()
Rocket::~Rocket()
**********
Falcon9::~Falcon9()
Rocket::~Rocket()
**********如果在基类中析构函数不加virtual,结果为:
Rocket::~Rocket()
***********
Rocket::~Rocket()
**********
Falcon9::~Falcon9()
Rocket::~Rocket()
**********另一种情况:
基类析构没有定义为virtual,而派生类(可能有多层)中有把析构定义为virtual的,此时用基类的指针指向派生类,再delete,会出错。
参考Effective C++ (第7条:要将多态基类的析构函数声明为虚函数)
需要记住的
- 应该为多态基类声明虚析构器。一旦一个类包含虚函数,它就应该包含一个虚析构器。
- 如果一个类不用作基类或者不需具有多态性,便不应该为它声明虚析构器。
版权声明:本文为feikudai8460原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。