C++虚析构函数和纯虚析构函数

C++虚析构函数和纯虚析构函数1、为什么要使用虚析构函数我们知道析构函数是在对象生命周期结束时自动被调用,用来做一些清理工作(如释放句柄,释放堆内存等),防止出现内存泄漏。那怎么还有虚析构函数呢?使用虚析构函数的类一般是要作为基类,被其他类继承。通过把基类的析构函数声明为虚函数,就可以通过父类指针来释放子类对象,从而完成子类的一些清理工作,防止出现内存泄漏。案例1:基类析构函数为非虚函数//test.hclassParent{public:Parent();~Parent

大家好,又见面了,我是你们的朋友全栈君。

1、为什么要使用虚析构函数

我们知道析构函数是在对象生命周期结束时自动被调用,用来做一些清理工作(如释放句柄,释放堆内存等),防止出现内存泄漏。

那怎么还有虚析构函数呢?

使用虚析构函数的类一般是要作为基类,被其他类继承。通过把基类的析构函数声明为虚函数,就可以通过父类指针来释放子类对象,从而完成子类的一些清理工作,防止出现内存泄漏。

案例1:基类析构函数为非虚函数

//test.h
class Parent
{
public:
        Parent();
        ~Parent();
private:
        int *p_ptr;
};

class Child : public Parent
{
public:
        Child();
        ~Child();
private:
        int *c_ptr;
};
//test.cpp
#include "test.h"
#include <iostream>

using namespace std;

Parent::Parent()
{
        p_ptr=new int;
        *p_ptr=10;
}

Parent::~Parent()
{
        cout << "Parent::~Parent() was called." << endl;
        if(p_ptr != 0)
        {
                delete p_ptr;
                p_ptr=0;
        }
}

Child::Child()
{
        c_ptr=new int;
        *c_ptr=20;
}
//main.cpp
#include "test.h"

void func(Parent *parent)
{
        delete parent;//通过父类指针来释放子类对象
}

int main(int argc, char *argv[])
{
        Child *child=new Child;

        func(child);
        return 1;
}

运行结果:

Parent::~Parent() was called.
结论:父类析构函数为非虚函数时,通过父类指针来释放子类对象时,只会调用父类的析构函数,而不会调用子类的析构函数,造成了子类的内存泄漏。所以,应该将父类的析构函数声明为虚函数。

案例2:父类的析构函数为虚函数

其他文件不用动,只需修改test.h,将父类的析构函数声明为虚函数。

//test.h
class Parent
{
public:
        Parent();
        virtual ~Parent();//虚析构函数
private:
        int *p_ptr;
};

class Child : public Parent
{
public:
        Child();
        ~Child();
private:
        int *c_ptr;
};

运行结果:

Child::~Child() was called.
Parent::~Parent() was called.
结论:只有将父类的析构函数声明为虚析构函数时,通过父类指针释放子类对象时,会先调用子类的析构函数,然后调用父类的析构函数,不存在内存泄漏问题。

2、纯虚析构函数

通过上面的虚析构函数知道,C++基类的析构函数最好声明为虚机构函数,那什么时候声明为纯虚析构函数呢?

我们知道,带有纯虚函数的类为抽象类,不能被实例化,只能被子类继承,所以当我们设计一个基类为抽象类时,可以把析构函数声明为纯虚析构函数,这样基类就是抽象类了。

注意:纯虚析构函数也要有函数体,用来做一些基类的清理工作,防止基类出现内存泄漏。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/149850.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • pycharm 激活码 2021【中文破解版】

    (pycharm 激活码 2021)这是一篇idea技术相关文章,由全栈君为大家提供,主要知识点是关于2021JetBrains全家桶永久激活码的内容https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~MLZPB5EL5Q-eyJsaWNlb…

    2022年3月21日
    53
  • 提升效率的秘密,仅需这一篇吃透负载均衡

    提升效率的秘密,仅需这一篇吃透负载均衡写在前面写本文的目的: 对负载均衡的理解零零散散,不成体系。 阅读这篇文章需要的条件: 对OSI模型有些许了解 有耐心。本文涉及大量的知识点,且只能用文字才能讲清楚,所以文字比较多。 收获: 读完此篇文章,从宏观的角度理解了负载均衡的原理以及实现机制。加深对分布式架构的了解 主要内容: 本文首先从概念开始,讲解什么是负载均衡,以及负载均衡在分布式系统中所承担的角色以及提供的功能。 讲解负载均衡的分类。分别从软硬件角度、地域范围角度以及…

    2022年7月19日
    9
  • 1g的树莓派4b能做什么_树莓派4B开发板简介

    1g的树莓派4b能做什么_树莓派4B开发板简介树莓派简介RaspberryPi(中文名为“树莓派”,简写为RPi,(或者RasPi/RPI)是为学生计算机编程教育而设计,只有信用卡大小的微型电脑,其系统基于Linux,随着Windows10IoT的发布,我们也将可以用上运行Windows的树莓派,别看其外表“娇小”,内“心”却很强大,视频、音频等功能通通皆有,可谓是“麻雀虽小,五脏俱全。树莓派由注册于英国的慈善组织“Raspber…

    2022年5月20日
    38
  • js 闭包传参_JavaScript闭包演示

    js 闭包传参_JavaScript闭包演示有个网友问了个问题,如下的html,为什么每次输出都是5,而不是点击每个p,就alert出对应的1,2,3,4,5。闭包演示functioninit(){varpAry=document.getElementsByTagName(“p”);for(vari=0;ipAry[i].onclick=function(){alert(i);}}}产品一产品二产品三产品四产品五解决方…

    2022年6月15日
    62
  • eclipse导入maven工程报错的解决「建议收藏」

    eclipse导入maven工程报错的解决「建议收藏」svn检出代码报错解决

    2022年5月31日
    95
  • Docker常用命令大全「建议收藏」

    Docker常用命令大全「建议收藏」Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化、容器是完全使用沙箱机制,彼此之间没有任何接口。一个完整的Docker有以下几个部分组成:DockerClient客户端Docker守护进程守护进程Docker镜像镜像Docker容器容器下面是Docker的常用命令:Docker常用命令大全容器生命周期管理命令runstart/stop/restart

    2022年9月18日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号