当前位置: 首页 > news >正文

【C/C++】虚析构和纯虚析构

纯虚析构的问题

多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码。

解决方式:将父类中的析构函数改为虚析构或者纯虚析构

虚析构和纯虚析构共性:

  • 可以解决父类指针释放子类对象
  • 都需要有具体的函数实现

虚析构和纯虚析构区别:

  • 如果是纯虚析构,该类属于抽象类,无法实例化对象

虚析构语法:

virtual ~类名(){}

纯虚析构语法:

virtual ~类名() = 0;

类名::~类名(){}

示例:

class Animal {
public:Animal(){cout << "Animal 构造函数调用!" << endl;}virtual void Speak() = 0;//析构函数加上virtual关键字,变成虚析构函数//virtual ~Animal()//{//	cout << "Animal虚析构函数调用!" << endl;//}virtual ~Animal() = 0;
};Animal::~Animal()
{cout << "Animal 纯虚析构函数调用!" << endl;
}//和包含普通纯虚函数的类一样,包含了纯虚析构函数的类也是一个抽象类。不能够被实例化。class Cat : public Animal {
public:Cat(string name){cout << "Cat构造函数调用!" << endl;m_Name = new string(name);}virtual void Speak(){cout << *m_Name <<  "小猫在说话!" << endl;}~Cat(){cout << "Cat析构函数调用!" << endl;if (this->m_Name != NULL) {delete m_Name;m_Name = NULL;}}public:string *m_Name;
};void test01()
{Animal *animal = new Cat("Tom");animal->Speak();//通过父类指针去释放,会导致子类对象可能清理不干净,造成内存泄漏//怎么解决?给基类增加一个虚析构函数//虚析构函数就是用来解决通过父类指针释放子类对象delete animal;
}int main() {test01();system("pause");return 0;
}

注意:即使是纯虚析构也需要有具体的实现。因为包含纯虚函数的类为抽象类,被继承后,在派生类析构函数被调用时抽象类析构函数也将被调用,因此必须有实现。唯一麻烦就是必须在类的定义之外(cpp文件)实现它。

总结:

​ 1. 虚析构或纯虚析构就是用来解决通过父类指针释放子类对象

​ 2. 如果子类中没有堆区数据,可以不写为虚析构或纯虚析构

​ 3. 拥有纯虚析构函数的类也属于抽象类



纯虚函数的实现案例:纯虚析构函数必须有实现

纯虚函数可以有实现:唯一麻烦就是必须在类的定义之外(cpp文件)实现它。
申明一个函数为纯虚并不意味着它没有实现,它意味着:

  • 当前类是抽象类 ;
  • 任何从此类派生的实体类必须将此函数申明为一个“普通”的虚函数(也就是说,
    不能带“= 0”)。

1、纯虚函数例子:

声明一个pure virtual 函数的目的是为了让 derived classes 只继承函数接口,派生类必须提供实现
可以为pure virtual函数提供实现,但使用时需要指明所属类,如:

//.h
class A{
public:virtual void func1() = 0;
};
class B : public A{
public:virtual void func1(){A::func1();};
};//.cpp
void A::func1(){..........}B b;
b.A::func1(); // 与b.func1()结果相同,相当于提供了缺省实现,但派生类需要主动指定。



2、纯虚析构函数必须有实现:

因为包含纯虚函数的类为抽象类,被继承后,在派生类析构函数被调用时抽象类析构函数也将被调用,因此必须有实现

class A{
public:virtual ~A() = 0;
};//.cpp
A::~A(){...}

总结:
1、纯虚函数可以有实现,但必须在类的定义之外(cpp文件)实现。
2、纯虚析构函数必须有实现。





参考链接:
纯虚函数的实现案例:纯虚析构函数必须有实现

http://www.lryc.cn/news/217434.html

相关文章:

  • 第四章 应用SysML基本特性集的汽车示例 P1|系统建模语言SysML实用指南学习
  • C语言 写一个简易音乐播放器
  • 面试题:有一个 List 对象集合,如何优雅地返回给前端?
  • DAY43 完全背包理论基础 + 518.零钱兑换II
  • unity 从UI上拖出3D物体,(2D转3D)
  • win10pycharm和anaconda安装和环境配置教程
  • [C++ 中]:6.类和对象下(static成员 + explicit +友元函数 + 内部类 + 编译器优化)
  • ONES Design UI 组件库环境搭建
  • 支付宝AI布局: 新产品助力小程序智能化,未来持续投入加速创新
  • taro全局配置页面路由和tabBar页面跳转
  • 【k8s】pod进阶
  • 【设计模式】第18节:行为型模式之“迭代器模式”
  • 【数据结构】单链表OJ题
  • 智能工厂架构
  • 阿里云多款ECS产品全面升级 性能最多提升40%
  • 责任链模式(Chain of Responsibility)
  • 文件管理技巧:根据大小智能分类并移动至目标文件夹
  • 具有自主产权的SaaS门店收银系统全套源码输出
  • 论文阅读:One Embedder, Any Task: Instruction-Finetuned Text Embeddings
  • [BUUCTF NewStarCTF 2023 公开赛道] week3 crypto/pwn
  • 软件测试---边界值分析(功能测试)
  • 使用pytorch处理自己的数据集
  • http进一步认识
  • grafana docker安装
  • 【Kubernetes】初识k8s--扫盲阶段
  • “01”滴答“摩尔斯电码”加密解密单个字符
  • P3817 小A的糖果
  • Yolov8目标识别与实例分割——算法原理详细解析
  • HandlerMethodArgumentResolver方法参数解析器支持多用户
  • 【Linux】 man命令使用