zoukankan      html  css  js  c++  java
  • 虚析构和纯虚析构

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

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

    虚析构和纯虚析构的共性:

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

    虚析构和纯虚析构的区别:

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

    虚析构语法:

    virtual ~类名(){}

    纯虚析构语法:

    virtual ~类名()=0;
    类名::类名(){};

     常规操作:

    #include<iostream>
    using namespace std;
    class animal
    {
    public:
        virtual void speak() = 0;
    };
    
    
    class dog : public animal
    {
    public:
        void speak()
        {
            cout << "小狗在说话" << endl;
        }
    };
    
    
    class cat : public animal
    {
    public:
        void speak()
        {
            cout << "小猫在说话" << endl;
        }
    };
    void test01()
    {
        animal* it = new cat;
        it->speak();
        delete it;
    }
    int main()
    {
        test01();
        system("pause");
    }

    但是如果子类对象有开辟空间到堆区时,在子类中创建指针:

    class cat : public animal
    {
    public:
        void speak()
        {
            cout << *m_name<<"小猫在说话" << endl;
        }
        cat(string name) {
            m_name =new string(name);
        }
        string* m_name;
    };
    void test01()
    {
        animal* it = new cat("tom");
        it->speak();
        delete it;
    }

    在父类子类对象中都打印一些字符会发现,子类的析构函数并没有调用,说明堆区并没有释放干净,这样就会造成内存泄露。

    这是因为父类指针在析构时并不会调用子类的析构函数,导致子类如果有堆区对象,就会造成内存泄露。

    cat类中有堆区属性,应该在该子类中将其释放,解决这个问就就需要虚析构

    虚析构的语法就是在父类析构函数前加上一个virtual关键字,结果:

    子类的析构函数已调用。

     以上就是利用父类指针解决子类对象时释放不干净的问题

    纯虚析构

    纯虚析构需要有什声明,也需要有具体 的实现;

    有了纯虚析构后这个类也属于抽象类,无法实例化对象;

    #include<iostream>
    #include<string>
    using namespace std;
    class animal
    {
    public:
        animal()
        {
            cout << "animal构造函数已调用" << endl;
        }
        //virtual ~animal()  //虚析构    虚析构与纯虚析构只能存在一个
        //{
        //    cout << "animal析造函数已调用" << endl;
        //}
        virtual ~animal() = 0; //纯虚析构声明
        virtual void speak() = 0;
    };
    animal::~animal() //纯虚析构具体实现
    {
        cout << "animal纯虚析构已调用" << endl;
    };
    
    class dog : public animal
    {
    public:
        void speak()
        {
            cout << "小狗在说话" << endl;
        }
    };
    
    
    class cat : public animal
    {
    public:
        void speak()
        {
            cout << *m_name<<"小猫在说话" << endl;
        }
        cat(string name) {
            cout << "cat构造函数已调用" << endl;
            m_name =new string(name);
        }
        ~cat()
        {
            if (m_name != NULL)
            {
                cout << "cat析构函数已调用" << endl;
                delete m_name;
                m_name = NULL;
            }
        }
    
        string* m_name;
    };
    void test01()
    {
        animal* it = new cat("tom");
        it->speak();
        delete it;
    }
    int main()
    {
        test01();
        system("pause");
    }

  • 相关阅读:
    线程的生命周期
    同步与死锁
    同步与死锁
    线程的休眠
    线程的休眠
    RTSP转RTMP、FLV、HLS网页无插件视频直播-LiveNVR功能介绍-音频开启
    使用LiveNVR实现将RTSP转RTMP、FLV、HLS,实现监控摄像头无插件直播
    使用LiveNVR实现安防摄像头RTSP流WEB无插件播放的延迟调优
    Javascript之数据执行原理探究
    Javascript之动画1
  • 原文地址:https://www.cnblogs.com/roscangjie/p/11419448.html
Copyright © 2011-2022 走看看