Em C++, por que uma classe derivada não pode chamar direta e explicitamente o destruidor de sua classe base sem usar um operador de resolução de escopo?
Ouvi dizer que em C++ todos os destruidores são processados pelo compilador em "destrutor", o que significa que os destruidores das classes base e derivadas têm o mesmo nome, levando à redefinição (ocultação).
Isso está correto?
#include <iostream>
struct base {
base() { std::cout << "base default \n"; }
~base() { std::cout << "~base \n"; }
};
struct derived : base {
derived() { std::cout << "derived default \n"; }
~derived()
{
//~base();No
base::~base();
std::cout << "~derived \n";
}
};
Eu sei que na prática quase não há necessidade de fazer isso, só quero entender o princípio...
Leia a mensagem de erro. Ela é bastante informativa:
A herança não é tão relevante, você obteria o mesmo erro para:
Se
base
tivesse sidooperator~
definido, essa linha criaria umbase
objeto temporário e chamaria o operador. Imagino que ninguém se importe com a ambiguidade sendo resolvida dessa forma, porque chamar o destruidor manualmente é muito raro. Observe também (de cppreference ):Pelo que sei, o único caso em que é aceitável chamar o destruidor explicitamente é quando você usa
placement-new
, que é bastante avançado e não é uma ferramenta comum. E mesmo assim, você deve chamar o destruidor correto para o objeto, em vez de apenas o destruidor de uma classe base.Além disso, assim como criar um objeto não é apenas uma chamada ao construtor, um objeto não é destruído corretamente apenas invocando o destruidor. Se você chamar o destruidor manualmente, também precisará desalocar manualmente a memória.
Em outras palavras, se você quiser fazer tudo manualmente, terá que fazer corretamente ou não fazer nada.
Para chamar o destruidor base, escreva:
Se você fizer isso no seu código, criá-lo
derived
e destruí-lo invocará um comportamento indefinido, pois o destruidor da classe base já foi chamado. Você não precisa fazer isso manualmente.