在继承的时候,父类的指针(或引用)可以指向(引用)子类的对象。如果子类有自己的指针属性,那么就需要将父类的析构函数声明为虚析构函数,否则通过父类指针(或者引用)无法调用子类的析构函数。
下面这段代码演示了这种情形
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using std::cout;
using std::endl;
class Parent
{
public:
int a, b;
char* name;
Parent(int a = 0, int b = 0,char *name = nullptr) //构造函数
{
this->a = a;
this->b = b;
this->name = (char*)malloc(strlen(name) + 1);
strcpy(this->name, name);
}
Parent(const Parent& p) //拷贝构造函数
{
this->a = p.a;
this->b = p.b;
this->name = (char*)malloc(strlen(p.name) + 1);
strcpy(this->name, name);
}
~Parent() //析构函数
{
if (nullptr != this->name)
{
free(this->name);
this->name = nullptr;
}
cout << "基类析构函数" << endl;
}
};
class Son : public Parent
{
public:
Son(int a = 0, int b = 0, char* name = nullptr,char* last_name = nullptr):Parent(a,b,name)
{
this->last_name = (char*)malloc(strlen(last_name) + 1);
strcpy(this->last_name, last_name);
}
~Son()
{
if (nullptr != this->last_name)
{
free(this->last_name);
this->last_name = nullptr;
}
cout << "派生类析构函数" << endl;
}
private:
char* last_name;
};
int main()
{
char name[10] = "White";
char last_name[10] = "Smith";
Parent *s = new Son(3, 4, name, last_name);
delete s;
return 0;
}
delete对象指针s的时候,并没有调用派生类的析构函数,这造成了内存泄漏。如果有很多都是父类指针指向子类对象的,并且程序一致不结束,那么这将是非常可怕的。为此C++为我们提供了虚析构。有了虚析构就不用太过担心内存泄漏的发生。
当我们在父类声明析构函数为虚析构。那么这时候delete对象指针s就不会有内存泄漏发生。
虚析构函数是为了解决这样的一个问题:基类的指针指向派生类对象,并用基类的指针删除派生类对象。
当一个类不作为基类使用的时候不要把它的析构函数声明为虚析构函数,这样会增加一个虚函数表。使类的体积增大。