web-dev-qa-db-fra.com

Dois-je appeler explicitement le destructeur virtuel de base?

Lors de la substitution d'une classe en C++ (avec un destructeur virtuel), je réimplémente le destructeur en tant que virtuel sur la classe héritante, mais dois-je appeler le destructeur de base?

Si donc j'imagine que c'est quelque chose comme ça ...

MyChildClass::~MyChildClass() // virtual in header
{
    // Call to base destructor...
    this->MyBaseClass::~MyBaseClass();

    // Some destructing specific to MyChildClass
}

Ai-je raison?

316
Nick Bolton

Non, les destructeurs sont appelés automatiquement dans l'ordre inverse de la construction. (Cours de base en dernier). N'appelez pas les destructeurs de classe de base.

428
Lou Franco

Non, vous n'avez pas besoin d'appeler le destructeur de base, un destructeur de base est toujours appelé pour vous par le destructeur dérivé. S'il vous plaît voir ma réponse liée ici pour l'ordre de destruction .

Pour comprendre pourquoi vous voulez un destructeur virtuel dans la classe de base, veuillez consulter le code ci-dessous:

class B
{
public:
    virtual ~B()
    {
        cout<<"B destructor"<<endl;
    }
};


class D : public B
{
public:
    virtual ~D()
    {
        cout<<"D destructor"<<endl;
    }
};

Quand tu fais:

B *pD = new D();
delete pD;

Ensuite, si vous n’avez pas de destructeur virtuel dans B, seul ~ B () sera appelé. Mais puisque vous avez un destructeur virtuel, d'abord ~ ​​D () sera appelé, puis ~ B ().

87
Brian R. Bondy

Ce que les autres ont dit, mais notez également qu'il n'est pas nécessaire de déclarer le destructeur virtuel dans la classe dérivée. Une fois que vous déclarez un destructeur virtuel, comme dans la classe de base, tous les destructeurs dérivés seront virtuels, que vous les déclariez ou non. En d'autres termes:

struct A {
   virtual ~A() {}
};

struct B : public A {
   virtual ~B() {}   // this is virtual
};

struct C : public A {
   ~C() {}          // this is virtual too
};
26
anon

Non. Contrairement aux autres méthodes virtuelles, où vous appelez explicitement la méthode Base à partir de la méthode Derived pour "chaîner" l'appel, le compilateur génère un code permettant d'appeler les destructeurs dans l'ordre inverse de l'appel de leurs constructeurs.

10
itsmatt

Non, vous n’appelez jamais le destructeur de la classe de base, il s’appelle toujours automatiquement comme d’autres l'ont fait remarquer, mais voici une preuve de concept avec des résultats:

class base {
public:
    base()  { cout << __FUNCTION__ << endl; }
    ~base() { cout << __FUNCTION__ << endl; }
};

class derived : public base {
public:
    derived() { cout << __FUNCTION__ << endl; }
    ~derived() { cout << __FUNCTION__ << endl; } // adding call to base::~base() here results in double call to base destructor
};


int main()
{
    cout << "case 1, declared as local variable on stack" << endl << endl;
    {
        derived d1;
    }

    cout << endl << endl;

    cout << "case 2, created using new, assigned to derive class" << endl << endl;
    derived * d2 = new derived;
    delete d2;

    cout << endl << endl;

    cout << "case 3, created with new, assigned to base class" << endl << endl;
    base * d3 = new derived;
    delete d3;

    cout << endl;

    return 0;
}

La sortie est:

case 1, declared as local variable on stack

base::base
derived::derived
derived::~derived
base::~base


case 2, created using new, assigned to derive class

base::base
derived::derived
derived::~derived
base::~base


case 3, created with new, assigned to base class

base::base
derived::derived
base::~base

Press any key to continue . . .

Si vous définissez le destructeur de classe de base comme virtuel, les résultats du cas 3 seraient identiques aux cas 1 et 2.

7
zar

Non, il est automatiquement appelé.

6
Benoît