通过阅读下面的代码以及将其置于编译器上编译运行:
#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; }
运行结果: