这篇博文所讲的是多态中的一个小BUG
我们知道,在构造函数中调用了new给指针分配内存,那么就要在析构函数中释放掉该内存;那么,如果在多态实验中 基类指针指向子类对象时会怎么样呢?
代码:
#include <iostream>
#include <string.h>
class Father {
public:
Father(const char *addr = "中国") {
std::cout << "调用了Father类的构造函数" << std::endl;
this->addr = new char[strlen(addr)+1];
strcpy_s(this->addr, strlen(addr)+1, addr);
}
~Father() {
std::cout << "调用了Fahter类的析构函数" << std::endl;
if (addr) {
delete addr;
addr = NULL;
}
}
private:
char *addr;
};
class Son : public Father {
public:
Son(const char *game = "吃鸡", const char *addr = "中国") : Father(addr) {
std::cout << "调用了Son类的构造函数" << std::endl;
this->game = new char[strlen(game)+1];
strcpy_s(this->game, strlen(game)+1, game);
}
~Son() {
std::cout << "调用了Son类的析构函数" << std::endl;
if (game) {
delete game;
game = NULL;
}
}
private:
char *game;
};
int main(void) {
std::cout << "---示例一---" << std::endl;
Father *father = new Father();
delete father;
std::cout << "---示例二---" << std::endl;
Son *son = new Son();
delete son;
std::cout << "---示例三---" << std::endl;
father = new Son();
delete father;
system("pause");
return 0;
}
运行截图:
在示例三中,竟然没有调用Son类的析构函数来释放内存,为什么会这样呢?
解决方案:
在基类的析构函数前加上 virtual 关键字
// 把Father类的析构函数定义为virtual函数时,
// 如果对 Father类的指针使用delete操作时,
// 就会对该指针使用“动态析构”:
// 如果这个指针,指向的是子类对象,
// 那么会先调用该子类的析构函数,再调用自己类的析构函数
virtual ~Father() {
std::cout << "调用了Fahter类的析构函数" << std::endl;
if (addr) {
delete addr;
addr = NULL;
}
}
运行截图:
【注意】
为了防止内存泄露,最好是在基类析构函数上添加virtual关键字,使基类析构函数为虚函数
目的在于,当使用delete释放基类指针时,会实现动态的析构:
1.如果基类指针指向的是基类对象,那么只调用基类的析构函数;
2.如果基类指针指向的是子类对象,那么先调用子类的析构函数,再调用父类的析构函数。
可别小看那一点点的内存就不要释放掉,积累成多,这个道理应该要懂得!