11.7.5重学C++之【虚析构和纯虚析构】

#include<stdlib.h>
#include<iostream>
#include<string>
using namespace std;



/*
    4.7.5 虚析构和纯虚析构
        多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码
        解决方式:将父类中的析构函数改为虚析构或者纯虚析构

        虚析构和纯虚析构共性:
            可以解决父类指针释放子类对象
            都需要有具体的函数实现
        虚析构和纯虚析构区别:
            如果是纯虚析构,该类属于抽象类,无法实例化对象

        虚析构语法:
            virtual ~类名(){}
        纯虚析构语法:
            virtual ~类名() = 0;
            类名::~类名(){}
*/



class Animal{
public:
    virtual void speak() = 0;

    Animal(){
        cout << "animal 构造" << endl;
    }

    /*
    ~Animal(){
        cout << "animal 析构" << endl;
    }
    */

    // 利用虚析构可以解决父类指针释放子类对象时不干净的问题
    virtual ~Animal(){
        cout << "animal 虚析构" << endl;
    }
};



class Cat : public Animal{
public:
    /*
    virtual void speak(){
        cout << "小猫喵喵叫" << endl;
    }
    */

    virtual void speak(){
        cout << *name << "小猫喵喵叫" << endl;
    }

    Cat(string _name){
        cout << "cat 构造" << endl;
        name = new string(_name);
    }

    ~Cat(){
        if(name != NULL){
            cout << "cat 析构 delete" << endl;
            delete name;
            name = NULL;
        }
    }

    string * name;
};




void test1(){
    /*
    Animal * animal = new Cat;
    animal->speak();
    delete animal;
    */

    Animal * animal = new Cat("tom");
    animal->speak();
    // 父类指针在析构时,不会调用子类析构,导致子类中若有堆区数据时,出现泄露
    // 解决办法:父类析构改为虚析构
    delete animal;
    /*
        父类正常析构时打印:
            animal 构造
            cat 构造
            tom小猫喵喵叫
            animal 析构
        问题:缺少了cat 析构,即delete name未生效,发生内存泄露
        父类析构改为虚析构后打印:
            animal 构造
            cat 构造
            tom小猫喵喵叫
            cat 析构 delete
            animal 析构
    */
}



int main()
{
    test1();

    system("pause");
    return 0;
}

#include<stdlib.h>
#include<iostream>
#include<string>
using namespace std;



/*
    4.7.5 虚析构和纯虚析构
        纯虚析构语法:
            virtual ~类名() = 0;
            类名::~类名(){}

        总结:
        ​ 1. 虚析构或纯虚析构就是用来解决通过父类指针释放子类对象
        ​ 2. 如果子类中没有堆区数据,可以不写为虚析构或纯虚析构
        ​ 3. 拥有纯虚析构函数的类也属于抽象类
*/



class Animal{
public:
    virtual void speak() = 0;

    Animal(){
        cout << "animal 构造" << endl;
    }

    /*
    // 利用虚析构可以解决父类指针释放子类对象时不干净的问题
    virtual ~Animal(){
        cout << "animal 虚析构" << endl;
    }
    */

    // 纯虚析构(需要声明+实现)
    // 有了纯虚析构之后,该类也属于抽象类,无法实例化对象
    virtual ~Animal() = 0; // 声明
};
Animal::~Animal(){
    cout << "animal 纯虚析构" << endl; // 实现
}



class Cat : public Animal{
public:

    virtual void speak(){
        cout << *name << "小猫喵喵叫" << endl;
    }

    Cat(string _name){
        cout << "cat 构造" << endl;
        name = new string(_name);
    }

    ~Cat(){
        if(name != NULL){
            cout << "cat 析构 delete" << endl;
            delete name;
            name = NULL;
        }
    }

    string * name;
};




void test1(){
    Animal * animal = new Cat("tom");
    animal->speak();
    delete animal;
}


int main()
{
    test1();

    system("pause");
    return 0;
}

posted @ 2021-03-18 10:38  yub4by  阅读(24)  评论(0编辑  收藏  举报