12.7.6 虚析构和纯虚析构
程序员文章站
2022-03-02 10:12:06
12.7.6 虚析构和纯虚析构多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码,这样子类中的堆区资源无法释放。解决方式:将父类中的析构函数改为虚析构或者纯虚析构虚析构和纯虚析构共性:可以解决父类指针释放子类对刻都需要有具体的函数实现虚析构和纯虚析构区别:如果是纯虚析构,该类属于抽象类,无法实例化对象我们来看之前的一个案例:class Animal{public:virtual void speak() = 0;Animal(){...
12.7.6 虚析构和纯虚析构
多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码,这样子类中的堆区资源无法释放。
解决方式:将父类中的析构函数改为虚析构或者纯虚析构
虚析构和纯虚析构共性:
- 可以解决父类指针释放子类对刻
- 都需要有具体的函数实现
虚析构和纯虚析构区别:
- 如果是纯虚析构,该类属于抽象类,无法实例化对象
我们来看之前的一个案例:
class Animal
{
public:
virtual void speak() = 0;
Animal()
{
cout << "Animal构造函数调用" << endl;
}
~Animal()
{
cout << "Animal析构函数调用" << endl;
}
};
class Cat :public Animal
{
public:
Cat(string name)
{
m_Name = new string(name);
cout << "Cat构造函数调用" << endl;
}
void speak()
{
cout << *m_Name << "小猫在说话" << endl;
}
string *m_Name;
~Cat()
{
if (m_Name != NULL)
{
delete m_Name;
m_Name = NULL;
}
cout << "Cat析构函数调用" << endl;
}
};
这里可以看到,Cat类多了一个属性,并且这个属性是定义再堆区的指针类型的字符串,所以要再析构函数里加上释放资源的代码。
我们来调用以下试试:
void test1()
{
Animal *animal = new Cat("Tom");
animal->speak();
delete animal;
}
int main()
{
test1();
}
可以看到运行时并没有显示Cat析构函数调用了。
那也就是说,Cat里的m_Name没有释放,一致等到程序关闭时才自动释放,这回造成内存泄漏,是一种漏洞。
那么怎么释放子类中的资源释放掉呢?
我们只需要将父类中的析构函数改为虚析构函数或者纯虚析构函数就行了。
- 虚析构函数:
class Animal
{
public:
virtual void speak() = 0;
Animal()
{
cout << "Animal构造函数调用" << endl;
}
virtual ~Animal()
{
cout << "Animal析构函数调用" << endl;
}
};
- 或者纯虚析构函数:
class Animal
{
public:
virtual void speak() = 0;
Animal()
{
cout << "Animal构造函数调用" << endl;
}
virtual ~Animal() = 0;
};
Animal::~Animal()
{
cout << "Animal析构函数调用" << endl;
}
再看运行结果,子类数据可以正常释放掉:
本文地址:https://blog.csdn.net/qq_32513033/article/details/107300809