Analyse approfondie des destructeurs virtuels et des destructeurs virtuels purs

question:

1. Comment résoudre le problème selon lequel lors de l'utilisation du polymorphisme , lorsqu'il y a des attributs dans la sous-classe ouverts sur la zone de tas , le pointeur de classe parent ne peut pas être appelé vers le code du destructeur de sous-classe lorsqu'il est publié ? ? ?


2. Que savez-vous du destructeur virtuel et du destructeur virtuel pur ? ? ?


Pourquoi le destructeur de Cat n'est-il pas appelé dans l'exemple suivant ?

#include<iostream>
#include<string>
using namespace std;
//动物类
class Animal{
    public:
    Animal(){
        cout<<"Animal的构造函数调用"<<endl;
    }
    //纯虚函数
    virtual void speak()=0;
    ~Animal(){
        cout<<"Animal的析构函数调用"<<endl;
    }
};
//猫类
class Cat:public Animal{
    public:
    Cat(string name){
        cout<<"Cat的构造函数调用"<<endl;
        m_Name=new string(name);//数据创建在堆区,用指针属性维护
    }


    //重写虚函数
    virtual void speak(){
        cout<<*m_Name<<"小猫在说话"<<endl;
    }

    ~Cat(){
        if(m_Name!=NULL){
            cout<<"Cat的析构函数调用"<<endl;
            delete m_Name;
            m_Name=NULL;
        }
    }

    string *m_Name;//为了让数据创建在堆区
};

int main()
{
    Animal *abs=new Cat("Tom");
    abs->speak();
    delete abs;
    return 0;
}

résultat de l'opération :

Appel du constructeur de l'animal Appel
du constructeur
du chat Tom le chat qui parle
Appel du destructeur de l'animal

raison:

Lorsque le polymorphisme est utilisé, s'il y a un attribut dans la sous-classe qui est alloué à la zone de tas, le pointeur de la classe parent ne peut pas être appelé sur le code destructeur de la sous-classe lorsqu'elle est libérée ! Il peut y avoir un problème de fuite de mémoire.

Solution:

Remplacez le destructeur de la classe parent par un destructeur virtuel ou un destructeur virtuel pur.


~~C'est la ligne de démarcation~~

Caractéristiques communes des destructeurs virtuels et des destructeurs virtuels purs :

  • Le pointeur de classe parent peut être résolu pour libérer l'objet de classe enfant
  • besoin d'avoir une implémentation de fonction spécifique

La différence entre destructeur virtuel et destructeur virtuel pur :

  • S'il s'agit d'un destructeur virtuel pur, la classe est abstraite et ne peut pas instancier d'objets

Méthode 1 : Remplacez le destructeur de la classe parent par un destructeur virtuel

L'utilisation du destructeur virtuel peut résoudre la situation où le pointeur de classe parent n'est pas propre pour libérer l'objet de classe enfant. 

Méthode 2 : Remplacez le destructeur de la classe parent par un destructeur virtuel pur, et il doit y avoir un processus d'implémentation de fonction.

Une classe avec un destructeur virtuel pur est appelée classe abstraite et ne peut pas instancier d'objets

résultat de l'opération :

Le constructeur de l'animal appelle
Le constructeur du chat appelle
Tom Chaton parle
Le destructeur du chat appelle
Le destructeur de l'animal appelle 

Temps d'utilisation : lorsque la sous-classe a une application de données dans la zone de tas, le pointeur de classe parent ne peut pas libérer l'objet de la sous-classe.

Code:

#include<iostream>
#include<string>
using namespace std;
//动物类
class Animal{
    public:
    Animal(){
        cout<<"Animal的构造函数调用"<<endl;
    }
    //纯虚函数
    virtual void speak()=0;
   
    //纯虚析构  必须要有函数的具体实现->父类中可能有需要释放的数据
    virtual ~Animal()=0;
};

Animal::~Animal(){
    cout<<"Animal的析构函数调用"<<endl;
}

//猫类
class Cat:public Animal{
    public:
    Cat(string name){
        cout<<"Cat的构造函数调用"<<endl;
        m_Name=new string(name);//数据创建在堆区,用指针属性维护
    }


    //重写虚函数
    virtual void speak(){
        cout<<*m_Name<<"小猫在说话"<<endl;
    }

    ~Cat(){
        if(m_Name!=NULL){
            cout<<"Cat的析构函数调用"<<endl;
            delete m_Name;
            m_Name=NULL;
        }
    }

    string *m_Name;//为了让数据创建在堆区
};

int main()
{
    Animal *abs=new Cat("Tom");
    abs->speak();
    delete abs;
    return 0;
}

Je suppose que tu aimes

Origine blog.csdn.net/zhangxia_/article/details/121357965
conseillé
Classement