Dois-je appeler explicitement le destructeur virtuel de base?

Lors du remplacement d’une classe en C ++ (avec un destructeur virtuel), j’implémente à nouveau le destructeur en tant que virtuel sur la classe héritée, mais dois-je appeler le destructeur de base?

Si oui, 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?

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

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 ici pour l’ordre de destruction .

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

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

Quand tu fais:

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

Ensuite, si vous n'aviez pas de destructeur virtuel dans B, seule ~ B () serait appelée. Mais comme vous avez un destructeur virtuel, d'abord ~ ​​D () sera appelé, puis ~ B ().

Ce que les autres ont dit, mais notez également que vous n’avez pas à déclarer le destructeur virtuel dans la classe dérivée. Une fois que vous déclarez un destructeur virtuel, comme vous le faites 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 }; 

Non. Contrairement aux autres méthodes virtuelles, où vous appelez explicitement la méthode Base à partir du mode Dérivé pour «chaîner» l’appel, le compilateur génère du code pour appeler les destructeurs dans l’ordre inverse dans lequel leurs constructeurs ont été appelés.

Non, c’est automatiquement appelé.

Non, vous n’appelez jamais le destructeur de classe bese, il est toujours appelé 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 la suivante:

 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 étant virtuel, vous devriez obtenir les mêmes résultats que les cas 1 et 2.