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++基类的析构函数最好声明为虚机构函数,那什么时候声明为纯虚析构函数呢?

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

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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 女朋友让我深夜十二点催她睡觉,我有Python我就不干

    用Python的pyautogui库自动操作电脑,并用apscheduler设置定时任务,实现定时发送微信功能。

  • 上海市高校计算机考试准考证

    上海市高校计算机考试准考证大家好啊,距离22考研初试仅剩26天,现在这个时候,大家除了对知识点进行查缺补漏之外,也得关注一些关于考前的准备工作,还有考场的注意事项哦!因为地区的不同,考点的不同,监考老师的不同,考试的要求和规定也会有差异哦,所以大家在拿到准考证之后,一定要仔细查看考试考点的要求~#考研倒计时#打开腾讯新闻,查看更多图片>1、可不可以戴手表、手环?如果要戴手表,那必须是没有记忆及计算功能的,也就是机械表,手环算电子产品大概率是不可以带的,在进考场之前可以询问一下监考老师,确认一下是否可以带

  • EagleEye: Fast Sub-net Evaluation for Efficient Neural Network Pruning(论文阅读)[通俗易懂]

    EagleEye: Fast Sub-net Evaluation for Efficient Neural Network Pruning(论文阅读)[通俗易懂]目录说明动机贡献方法发现EagleEye剪枝算法实验实验1-相关性的定量分析实验2-基于自适应BN的评估方法的通用性实验3-从修剪候选中选择最佳修剪策略的计算成本实验4-Effectivenessofourproposedmethod总结与讨论说明找出训练好的深度神经网络(DNN)的计算冗余部分是剪枝算法要解决的关键问题。许多算法都试图通过引入各种评估方法来预测修剪后的子网的模型性能。在这个工作中,我们提出了一种称为EagleEye的剪枝方法,其中使用了一个基于自适应批归一化adaptiv

  • rsync自动同步_文件实时同步

    rsync自动同步_文件实时同步文章目录一、rsync同步简介1.关于rsync2.rsync同步源(备份源)二、配置rsync备份源1.关闭防火墙2.查看rsync是否已安装,一般系统已默认安装rsync3.建立/etc/rsync.conf配置文件4.为备份账户创建数据文件5.保证所有用户对源目录/var/www/html都有读取权限6.启动rsync服务程序7.关闭rsync服务8.编写测试网页三、rsync命令基本用法1.基本格式2.常用选项四、配置发起端1.关闭防火墙2.查看rsync是否已安装,一般

    2022年10月13日
  • 神经网络的反向传播算法推导

    神经网络的反向传播算法推导有了上一篇神经网络的反向传播算法推导—前期知识准备做铺垫,下一步来看看反向传播算法具体的推导过程。一、定义机器学习中常说的两个函数:损失函数(lossfunction):是定义在单个样本上的,算的是一个样本的值和预测值的误差,记为C(Θ);代价函数(costfunction):是定义在整个训练集上的,是所有样本误差的平均,也就是损失函数的平均,记为J(Θ);假设函数:二、神经网络结构图以三层神经网络为例:…

  • python语言变量命名规则[通俗易懂]

    python语言变量命名规则[通俗易懂]Python语言变量命名规则变量名只能包含字母、数字和下划线。(推荐学习:0基础入门python)变量名可以字母或下划线开头,但不能以数字开头。例如,可将变量命名为message_1,但不能将其命名为1_message。变量名不能包含空格,但可使用下划线来分隔其中的单词。例如,变量名greeting_message可行,但变量名greetingmessage会引发错误。不要将Pytho…

发表回复

您的电子邮箱地址不会被公开。

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