通过阅读下面的代码以及将其置于编译器上编译运行:
#include<iostream>
using namespace std;
class Father {
public:
Father(const char* addr="中国") {
cout << "执行Father类构造函数" << endl;
int len = strlen(addr) + 1;
this->addr = new char[len];
strcpy_s(this->addr, len, addr);
}
~Father() {
cout << "执行Father类析构函数" << endl;
delete addr;
addr = NULL;
}
private:
char* addr;
};
class Son :public Father {
public:
Son(const char* game="联盟",const char*addr="中国"):Father(addr) {
cout << "执行Son类构造函数" << endl;
int len = strlen(game) + 1;
this->game = new char[len];
strcpy_s(this->game, len, game);
}
~Son() {
cout << "执行Son类析构函数" << endl;
delete game;
game = NULL;
}
private:
char* game;
};
int main(void) {
cout << "----case 1----" << endl;
Father* father = new Father();
delete father;
cout << endl;
cout << "----case 2----" << endl;
Son* son = new Son();
delete son;
cout << endl;
system("pause");
return 0;
}
运行结果:
结果完全符合我们的预期,但是就此可以说明我们的代码就完全正确或者说不存在致命错误???
我们不妨在源代码中加入这样一种情况:用父类指针指向子类对象
Father* father = new Son();
delete father;
完整代码:
#include<iostream>
using namespace std;
class Father {
public:
Father(const char* addr="中国") {
cout << "执行Father类构造函数" << endl;
int len = strlen(addr) + 1;
this->addr = new char[len];
strcpy_s(this->addr, len, addr);
}
~Father() {
cout << "执行Father类析构函数" << endl;
delete addr;
addr = NULL;
}
private:
char* addr;
};
class Son :public Father {
public:
Son(const char* game="联盟",const char*addr="中国"):Father(addr) {
cout << "执行Son类构造函数" << endl;
int len = strlen(game) + 1;
this->game = new char[len];
strcpy_s(this->game, len, game);
}
~Son() {
cout << "执行Son类析构函数" << endl;
delete game;
game = NULL;
}
private:
char* game;
};
int main(void) {
Father* father = new Son();
delete father;
cout << endl;
system("pause");
return 0;
}
运行结果:
我们会惊奇的发现:子类的析构函数没有被执行 ,这样将会导致内存泄漏,引发严重后果;
重要:
为了防止内存泄漏,最好是在基类(父类)析构函数上添加virtual关键字,使基类析构函数为虚函数
目的在于:
当使用delete释放基类指针时,会实现动态的析构;
如果基类指针指向的是基类对象,那么只调用基类的析构函数;
如果基类指针指向的是子类对象,那么先调用子类的虚构函数,再调用父类的析构函数.
正确代码:
#include<iostream>
using namespace std;
class Father {
public:
Father(const char* addr="中国") {
cout << "执行Father类构造函数" << endl;
int len = strlen(addr) + 1;
this->addr = new char[len];
strcpy_s(this->addr, len, addr);
}
virtual ~Father() {
cout << "执行Father类析构函数" << endl;
delete addr;
addr = NULL;
}
private:
char* addr;
};
class Son :public Father {
public:
Son(const char* game="联盟",const char*addr="中国"):Father(addr) {
cout << "执行Son类构造函数" << endl;
int len = strlen(game) + 1;
this->game = new char[len];
strcpy_s(this->game, len, game);
}
~Son() {
cout << "执行Son类析构函数" << endl;
delete game;
game = NULL;
}
private:
char* game;
};
int main(void) {
cout << "----case 1----" << endl;
Father* father = new Father();
delete father;
cout << endl;
cout << "----case 2----" << endl;
Son* son = new Son();
delete son;
cout << endl;
cout << "----case 3----" << endl;
father = new Son();
delete father;
cout << endl;
system("pause");
return 0;
}