多态是C++的一个重要特性,但是再使用多态的时候又有 非常多的陷阱,例如这个析构函数,请看下面的代码
#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;
class Father
{
public:
Father(const char* _name = "无名")
{
cout << __FUNCTION__ << endl;
int lenth = strlen(_name) + 1;
this->name = new char[lenth];
strcpy_s(this->name, lenth, _name);
}
// 动态析构
virtual ~Father()
{
cout << __FUNCTION__ << endl;
if (this->name) {
delete this->name;
}
this->name = nullptr;
}
private:
char* name;
};
class Son final : public Father
{
public:
Son(const char* _game = "LOL", const char* _name = "张云翔"):
Father(_name)
{
cout << __FUNCTION__ << endl;
int lenth = strlen(_game) + 1;
this->game = new char[lenth];
strcpy_s(this->game, lenth, _game);
}
~Son()
{
cout << __FUNCTION__ << endl;
if (this->game) {
delete game;
}
game = NULL;
}
private:
char* game;
};
int
main(int agrc, char** argv)
{
string line(50, '-');
Father *fa = new Father;
delete fa;
cout << line << endl;
Son *so = new Son;
delete so;
cout << line << endl;
// 多态得形式
fa = new Son;
delete fa;
system("pause");
return 0;
}
这个代码是没有问题的,但是如果把父类中析构函数前的virtual 去掉,大家可能看着是没有错误,但是如果去掉的话就会是这个结果,大家会发现怎么成双成对的析构 和构造函数 第三个部分怎么少一个(意味着又内存泄漏,如果再服务器哪种一直运行的案例上是特别可怕的)
在父类的析构函数前加上virtual 后 结果:
总结:
把Father类的析构函数定义为virtual函数时,
如果对 Father类的指针使用delete操作时,
就会对该指针使用“动态析构”:
如果这个指针,指向的是子类对象,
那么会先调用该子类的析构函数,再调用自己类的析构函数
【注意】
为了防止内存泄露,最好是在基类析构函数上添加virtual关键字,使基类析构函数为虚函数
目的在于,当使用delete释放基类指针时,会实现动态的析构:
如果基类指针指向的是基类对象,那么只调用基类的析构函数
如果基类指针指向的是子类对象,那么先调用子类的析构函数,再调用父类的析构函数