栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++多态之虚析构与纯虚析构

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++多态之虚析构与纯虚析构

一、虚析构与纯虚析构的共同点:
  1. 都是释放子类的堆区资源。
  2. 都需要具体实现。
二、虚析构与纯虚析构的不同点: 
  1. 使用纯虚析构函数的父类属于抽象类,不能实例化具体对象。代码示例如下:
    #include 
    
    // 父类
    class Base
    {
        public:
            
            // 纯虚析构函数
            virtual ~Base() = 0;
    
    };
    
    // 纯虚析构函数的实现,此处必须实现,因为是析构函数,可能会释放父类的堆区资源,否则代码会报错
    Base::~Base()
    {
        std::cout << "父类的纯虚析构函数调用" << std::endl;
    }
    
    class Son : public Base
    {
        public:
            
            // 子类析构函数的实现
            virtual ~Son()
            {
                std::cout << "子类的析构函数调用" << std::endl;
            }
    };
    
    int main()
    {
        // 实例化失败,此处代码会报错,因为父类有纯虚析构函数,是抽象类
        // Base * base = new Base;
    
        // 实例化成功,因为子类不是抽象类
        Base * base = new Son;
    
        system("pause");
        return 0;
    }
  2. 使用虚析构函数的父类不属于抽象类,可以实例化具体对象。代码实例如下:
    #include 
    
    class Father
    {
        public:
            
            // 父类的虚析构函数
            virtual ~Father()
            {
                std::cout << "父类的虚析构函数调用" << std::endl;
            }
    
    };
    
    int main()
    {
        // 此时父类实例化成功,因为父类不是抽象类,代码不会报错
        Father * father = new Father;
    
        system("pause");
        return 0;
    }
 三、虚析构与纯虚析构的作用

解决父类指针父类引用无法释放子类资源导致的内存泄露问题 。

现在可以来做个对比,首先写一个无虚析构或无纯虚析构的父类代码案例,看看最后的打印信息

  • 无虚析构或无纯虚析构的父类代码案例:
#include 
using namespace std;

class Father
{
    public:
        
        // 父类的析构函数
        ~Father()
        {
            std::cout << "父类的析构函数调用" << std::endl;
        }
};

class Son : public Father
{
    public:
        
        // 子类的析构函数
        ~Son()
        {
            std::cout << "子类的析构函数调用" << std::endl;
        }
};

int main()
{
    Father * father = new Son;
    delete father;

    system("pause");
    return 0;
}

 运行结果截图如下,可见未调用子类的析构函数,如果此时的子类申请了堆区资源,必将造成内存泄露问题:

  •  有虚析构或纯虚析构的父类代码案例
#include 

class Father
{
    public:
        
        // 父类的构造函数
        Father()
        {
            std::cout << "父类的构造函数调用" << std::endl;
        }

        // 父类的虚析构函数
        virtual ~Father()
        {
            std::cout << "父类的虚析构函数调用" << std::endl;
        }

};

class Son : public Father
{
    public:
        
        // 子类的构造函数
        Son(std::string name)
        {
            std::cout << "子类构造函数的调用" << std::endl;

            // 子类申请堆区资源
            m_Name = new std::string(name);
        }

        ~Son()
        {

            std::cout << "子类析构函数的调用" << std::endl;

            // 析构子类的堆区资源
            if (m_Name != NULL)
            {
                delete m_Name;
                m_Name = NULL;
            }
        }

        // 此处为字符串指针变量,是为了申请堆区资源做准备
        std::string * m_Name;
};

int main()
{
    Father * father = new Son("Jack");
    delete father;

    system("pause");
    return 0;
}

 运行结果截图如下,在此段代码中,父类使用了虚析构函数,子类申请了堆区资源,在释放父类资源的同时也释放了子类资源。

 


如果喜欢此文章,可以点赞哦,我会无偿分享所有源码与自己的C++成长之路 !

 

 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1038503.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号