C++中虚析构函数的作用及其原理分析

C++笔记之虚析构函数的作用 如果基类的析构函数不是虚函数,那么只会调用基类的析构函数,而不会调用派生类的析构函数。虚析构函数是一种特殊类型的析构函数,在基类中声明为虚函数,并且在派生类中可以被重写。它用于正确释放派生类对象的资源,即使通过基类指针删除派生类对象时也能够调用正确的析构函数。它与类的构造函数相对应,当对象的生命周期结束时(例如对象被销毁或超出其作用域),析构函数会被自动调用。总结来说,当使用继承和多态性时,通常应该将基类的析构函数声明为虚函数,并在派生类中重写它,以确保正确释放派生类对象的资源。函数中,通过基类指针。 阅读详情
AI摘要

本文详细介绍了C++中虚析构函数的作用及其原理。通过实例解释了虚析构函数如何避免内存泄露,特别是在使用基类指针删除派生类对象时。还探讨了虚析构函数的实现机制。

参考http://blog.youkuaiyun.com/xiamentingtao/article/details/55517203

C++中的虚析构函数到底什么时候有用的,什么作用呢。
一.虚析构函数的作用
总的来说虚析构函数是为了避免内存泄露,而且是当子类中会有指针成员变量时才会使用得到的。也就说虚析构函数使得在删除指向子类对象的基类指针时可以调用子类的析构函数达到释放子类中堆内存的目的,而防止内存泄露的.

我们知道,用C++开发的时候,用来做基类的类的析构函数一般都是虚函数。可是,为什么要这样做呢?下面用一个小例子来说明:

#include<iostream>
using namespace std;

class ClxBase
{
    public:
        ClxBase() {};
        virtual ~ClxBase() { cout<<"delete ClxBase"<<endl; };

        virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl;  };

};

class ClxDerived : public ClxBase
{
    public:
        ClxDerived() {};
        ~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl;  };

        void DoSomething() { cout << "Do something in class ClxDerived!" << endl;  };

};

int main(int argc, char const* argv[])
{
     ClxBase *pTest = new ClxDerived;
     pTest->DoSomething();
     delete pTest;
    return 0;
}

这里写图片描述
但是,如果把类ClxBase析构函数前的virtual去掉,那输出结果就是下面的样子了:
这里写图片描述
没有调动子类的析构函数
也就是说,类ClxDerived的析构函数根本没有被调用!一般情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。我想所有的C++程序员都知道这样的危险性。当然,如果在析构函数中做了其他工作的话,那你的所有努力也都是白费力气。
所以,文章开头的那个问题的答案就是--这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。
当然,并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。

总结一下虚析构函数的作用:
(1)如果父类的析构函数不加virtual关键字
当父类的析构函数不声明成虚析构函数的时候,当子类继承父类,父类的指针指向子类时,delete掉父类的指针,只调动父类的析构函数,而不调动子类的析构函数。
(2)如果父类的析构函数加virtual关键字
当父类的析构函数声明成虚析构函数的时候,当子类继承父类,父类的指针指向子类时,delete掉父类的指针,先调动子类的析构函数,再调动父类的析构函数。
二.虚析构函数的原理分析

#include<iostream>
using namespace std;

class Base
{
public:
    Base(){cout<<"create Base"<<endl;}
    virtual ~Base(){cout<<"delete Base"<<endl;}
};

class Der : public Base
{
public:
    Der(){cout<<"create Der"<<endl;}
    ~Der(){cout<<"Delete Der"<<endl;}
};
int main(int argc, char const* argv[])
{
    Base *b = new Der;
    delete b;

    return 0;
}

从创建讲起,用gdb调试你会发现,
(1)先调用父类的构造函数,再调用子类的构造函数,

这里有一个问题:父类的构造函数/析构函数与子类的构造函数/析构函数会形成多态,但是当父类的构造函数/析构函数即使被声明virtual,子类的构造/析构方法仍无法覆盖父类的构造方法和析构方法。这是由于父类的构造函数和析构函数是子类无法继承的,也就是说每一个类都有自己独有的构造函数和析构函数。

(2)而由于父类的析构函数为虚函数,所以子类会在所有属性的前面形成虚表,而虚表内部存储的就是父类的虚函数

即使子类也有虚函数,但是由于是单继承,所以也只有一张虚表,这在上一篇博客多态中讲到过。
执行 Base *b = new Der;之后b的最终形态
这里写图片描述

(3)当delete父类的指针时,由于子类的析构函数与父类的析构函数构成多态,所以得先调动子类的析构函数;之所以再调动父类的析构函数,是因为delete的机制所引起的,delete 父类指针所指的空间,要调用父类的析构函数。
所以结果就是这样
这里写图片描述

详解C++中虚析构函数的作用及其原理分析 主要介绍了C++中虚析构函数的作用及其原理分析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 立即下载

相关推荐

解析C++中虚析构函数的作用

本篇文章是对C++中虚析构函数的作用进行了详细的分析介绍,需要的朋友参考下

多态 进阶(虚析构,纯虚函数,纯虚析构)

虚函数 纯虚函数 虚析构 纯虚析构(重要) 重写 重载 重定义(了解)

兰天禄的博客 3534

VLA、世界模型与端到端在智驾中的本质关系与工程落地

世界模型并非3D重建,而是对环境状态转移函数的可微分建模;VLA不是视觉+语言+动作的简单拼接,核心在于跨模态语义对齐。二者共同支撑具身智能系统实现从感知到行动的闭环推演,其技术价值体现在长尾场景泛化能力提升与决策延迟降低。在自动驾驶领域,真实量产方案均采用VLA架构作为多模态感知基础,嵌入轻量级世界模型以支持反事实轨迹推演,并通过WA硬件封装保障实时性,最终由端到端控制层完成像素到扭矩的语义贯通。这种混合架构已成L2+/L3智驾系统的工程共识。

weixin_34163553的博客 365

C++中的虚析构

首先什么是虚析构,虚析构就是析构函数为虚函数。 那么为什么要用虚析构呢,是为了delete基类指针指向派生类时防止子类得数据不会被释放造成内存泄露。 我们看一下下面的例子: 首先我们定义一个数据类,MyData class MyData { public: MyData(){ m_Data = new char[10]; } ~MyData() { delete[] m_Data; ...

不会飞的纸飞机的博客 9169

喷雾破碎模型解析:从理论到CFD应用实践

本文深入解析喷雾破碎模型的理论基础与CFD应用实践,重点介绍KHRT、TAB和ETAB等主流模型的核心原理与工程调参技巧。通过OpenFOAM实例演示和参数优化建议,帮助工程师精准预测液滴破碎行为,提升燃烧效率与排放控制性能,适用于汽车发动机、燃气轮机等工业场景。

weixin_29281915的博客 499

LIN总线从入门到精通:低成本汽车通信协议原理与实战

在汽车电子和嵌入式系统中,串行通信协议是实现分布式控制的关键技术。其中,LIN(Local Interconnect Network)总线作为一种专为低成本应用设计的单主多从网络协议,其核心原理在于通过简化的“领导-汇报”通信模式,在满足车身控制、传感器数据采集等场景需求的同时,将硬件与布线成本降至最低。LIN总线采用标准化的帧结构,包含间隔场、同步场和受保护标识符场,并依赖调度表来管理通信时序,确保了网络的确定性与可靠性。其技术价值在于为车窗、座椅、灯光等非安全关键系统提供了高性价比的解决方案,是构建分层

weixin_29185167的博客 261

虚析构函数详解

众所周知,virtual函数(虚函数),是实现动态调度(运行时多态) 概念:当基类指针指向子类对象时候,虚函数能实现运行时多态(多态指:同一个接口的不同实现方式) 虚析构函数:当基类指针指向指针对象的时候,需要把基类的析构函数设置成虚析构,防止内存泄露 1、当基类析构函数不设置为虚析构 class BaseClass { public: BaseClass() {} ~BaseCl...

qq_15821883的博客 1万+

用示波器抓一次MIPI D-PHY的波形,手把手教你读懂HS模式和LP模式的切换时序

本文详细解析了MIPI D-PHY信号的双模切换机制,包括高速模式(HS)和低功耗模式(LP)的波形捕获与诊断技巧。通过示波器设置、关键状态分析和实战案例,帮助工程师快速定位信号完整性问题,提升调试效率。

weixin_30696427的博客 457

C++语言中的虚析构和纯虚析构【详细讲解】

本篇文章主要对C++中的虚析构和纯虚析构进行了讲解,希望读者可以通过复现代码更好的理解虚析构和纯虚析构的作用。

weixin_45688108的博客 3143

【计算机视觉】基于复杂环境下的车牌识别

本文针对复杂环境下(光照变化、车牌变形、噪声干扰)的车牌识别问题,提出了一套完整的优化方案。通过四个核心环节进行改进:1)采用CLAHE、同态滤波等技术优化光照处理;2)使用边缘检测和透视变换应对车牌变形;3)结合中值滤波和暗通道去噪算法消除干扰;4)改进字符分割与识别方法。文章提供了详细的Python实现代码,展示了从预处理到字符识别的完整流程,并通过多策略融合显著提升了复杂场景下的识别准确率。实验结果表明,该方法能有效应对各类复杂环境挑战,为实际应用提供了可靠解决方案。

2401_84149564的博客 1628

单细胞分析实战:当Seurat的SCTransform遇上Harmony,我的整合流程优化笔记

本文详细介绍了单细胞转录组数据分析中SCTransform与Harmony整合流程的优化策略。通过实战案例展示如何调整SCTransform参数、优化Harmony整合效果,并解决常见问题,帮助研究者获得更可靠的生物学发现。特别适合需要处理批次效应的单细胞数据分析人员。

weixin_42552716的博客 360

C++中的虚析构函数

这里有一个问题:父类的构造函数/析构函数与子类的构造函数/析构函数会形成多态,但是当父类的构造函数/析构函数即使被声明virtual,子类的构造/析构方法仍无法覆盖父类的构造方法和析构方法。当父类的析构函数不声明成虚析构函数的时候,当子类继承父类,父类的指针指向子类时,delete掉父类的指针,只调动父类的析构函数,而不调动子类的析构函数。当父类的析构函数声明成虚析构函数的时候,当子类继承父类,父类的指针指向子类时,delete掉父类的指针,先调动子类的析构函数,再调动父类的析构函数。

quaer的博客 1299

Qt实现窗口等比例缩放

在Qt中,实现窗口的等比例缩放是一个常见的需求。通过对窗口的尺寸进行调整,使得窗口的内容在缩放过程中保持相同的比例,可以提供更好的用户体验。通过以上的代码,我们实现了一个可以等比例缩放的Qt窗口。在调整窗口大小时,窗口中的标签和按钮将按比例缩放,保持内容的比例不变。首先,我们需要在Qt中创建一个窗口,并设置其内容。在该事件中,我们将根据窗口的新尺寸计算出合适的比例因子,并将其应用到窗口的内容上。现在,我们将添加功能,使得窗口可以等比例缩放。最后,我们将缩放因子应用到窗口中的标签和按钮上,调整它们的尺寸。

2301_79330511的博客 3959

【C++】什么是多态?虚函数的底层实现原理|多重继承|菱形继承

看到一个说明很好,转过来: 在C++中,多态是利用虚函数来实现的。比如说,有如下代码: #include <iostream> using namespace std; class Animal { public: void Cry() { cout << "Animal cry!" << endl; } }; class Dog :pub...

我的笔记本 1184

021、反激变换器的软启动设计

本文分享了反激变换器软启动设计的实践经验。作者通过一次上电炸机事故引出软启动的重要性,分析了启动瞬间电流冲击和环路饱和问题。介绍了三种软启动方案:效果差的RC电路、推荐使用的数字芯片方案以及分立元件实现方法,重点指出数字方案的一致性优势。文章还探讨了软启动与过流保护的配合问题,提供了实测波形、温度影响等调试要点,并总结出软启动时间选择、批量生产一致性等实用建议。最后强调软启动是电源可靠性的关键设计,不应为节省成本而忽略。全文包含多个工程实践细节,对电源设计人员具有重要参考价值。(149字)

Jack010169的博客 178

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C++中的多态

摘要:C++多态的实现基于虚函数机制,需要满足两个必要条件:(1)通过父类指针或引用调用函数;(2)在派生类中重写父类虚函数(函数名、参数列表和返回类型必须相同)。虚函数通过虚函数表实现动态绑定,每个含有虚函数的类会生成虚函数表,对象中包含指向该表的指针。特别地,基类析构函数应当声明为虚函数,以确保正确释放派生类资源。虚函数重写允许协变返回类型,且父类虚函数特性会自动继承给子类。正确使用虚函数机制是保证多态行为的关键。

2302_79616021的博客 895

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

C++基础语法----多态

[](()1.实现多态的三个先决条件 进行了类的继承; 子类与父类写了结构相同的函数(并且基类的函数是虚的); 使用了基类指针指向了子类的对象 [](()2.语法 //语法(条件1,2): calss A{ public: virtual void print(){} }; class B:public A{ public: void print(){} }; //语法(条件3) int main(){ A *p; B q; p=&q;(基类的指针指向子类的对象)//此时便可以进

m0_67619362的博客 541

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

C++多态

C++多态机制解析:动态多态的实现与原理

2301_79383371的博客 757
上一篇: C++隐藏规则再分析
下一篇: STL库基本数据算法的使用(一)
逐鹿之城
博客等级 码龄11年 240粉丝 178原创
评论 21
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值