author:&Carlton
tag:C++
topic:【C++】 虚析构和纯虚析构,Visual Studio开发人员工具查看类内部结构cl /d1 reportSingleClassLayout
website:黑马程序员C++
date::2023年7月29日
目录
虚析构和纯虚析构
案例
注意点
类内部结构变化
虚析构和纯虚析构
如果子类有属性建立在堆区,那么父类指针在释放时无法调用子类析构函数(先前用父类指针定义子类对象实行运行多态),需用通过父类使用虚析构 / 纯虚析构函数来解决。
是在父类使用虚析构或纯虚虚构函数,要求有非空的函数体,以防在父类有建立在堆区内存区的数据不能及时释放造成内存泄漏。
案例
源代码:
#include <iostream>
#include <string>
using namespace std;
class Animal
{
public:
Animal()
{
cout << "Animal的构建函数" << endl;
}
~Animal()
{
cout << "Animal的析构函数" << endl;
}
//纯虚函数
virtual void speak() = 0;
};
class Cat :public Animal
{
public:
string* m_name;
Cat(string name)
{
//建立内存在堆区
m_name = new string(name);
cout << "Cat的构建函数" << endl;
}
~Cat()
{
//释放堆内存区上内存
if (m_name != NULL)
{
cout << "Cat的析构函数" << endl;
delete m_name;
m_name = NULL;
}
}
void speak()
{
cout << *m_name << "小猫在说话" << endl;
}
};
void test01()
{
Animal* animal = new Cat("Tom");
animal->speak();
delete animal;
}
int main()
{
test01();
return 0;
}
运行结果:
缺少子类Cat的析构函数实现过程,堆内存区数据无法释放,带来数据泄露问题。验证如果子类有属性建立在堆区,那么父类指针在释放时无法调用子类析构函数(先前用父类指针定义子类对象实行运行多态)
给父类Animal析构函数使用virtual修饰为虚析构函数后:
注意点
父类(纯)虚析构函数的函数体不能为空。
class Animal
{
public:
Animal()
{
cout << "Animal的构建函数" << endl;
}
//虚析构函数
//virtual ~Animal()
//{
// cout << "Animal的析构函数" << endl;
//}
//纯虚析构函数
virtual ~Animal() = 0;
//纯虚函数
virtual void speak() = 0;
};
//纯虚析构函数的函数体实现
Animal::~Animal()
{
cout << "Animal的纯析构函数" << endl;
}
类内部结构变化
使用virtual修饰父类析构函数前:
使用虚析构函数后:
虚函数表中多了&Cat :: {dtor}的入口,是子类Cat函数的析构函数入口,在程序运行时实现运行多态(父类指针Animal指向建立在堆区的子类对象Cat)
欢迎指正与分享,谢谢!