Deve cada classe tem um destrutor virtual?

votos
45

Java e C # suportam a noção de classes que não podem ser utilizados como classes base com o finale sealedpalavras-chave. Em C ++ no entanto não há nenhuma boa maneira de evitar uma classe de ser derivada a partir do qual deixa o autor da classe com um dilema, deve cada classe tem um destrutor virtual ou não?


Edit: Como C ++ 11 isso não é mais verdade, você pode especificar que uma classe é final.


Por um lado, dar a um objecto um processo de destruição virtual significa que vai ter um vtablee, por conseguinte, consomem quatro (ou oito em máquinas de 64 bit) bytes adicionais por objeto para o vptr.

Por outro lado, se alguém depois deriva desta classe e elimina uma classe de derivados por meio de um ponteiro para a classe base o programa vai ser mal definidas (devido à ausência de um processo de destruição virtual), e francamente optimizar para um ponteiro por objecto está ridículo.

No lado de preensão tendo um processo de destruição virtual (possivelmente) anuncia que este tipo se destina a ser utilizado polimorficamente.

Algumas pessoas pensam que você precisa de uma razão explícita para não usar um destruidor virtual (como é o subtexto de esta questão ) e outros dizem que você deve usá-los somente quando você tem razão para acreditar que sua classe é para ser derivado, o que você pensar?

Publicado 09/12/2008 em 19:56
fonte usuário
Em outras línguas...                            


8 respostas

votos
53

Cada classe abstrata deve quer ter um,

  • destruidor protegido, ou,
  • destrutor virtual.

Se você tem um destrutor não-virtual público, isso não é bom, uma vez que permite aos utilizadores eliminar através desse ponteiro de um objeto derivado. Desde como todos sabemos, isso é um comportamento indefinido.

Para uma classe não se destina a eliminar através de um ponteiro para ele, não há nenhuma razão para ter um destrutor virtual. Seria não só desperdiçar recursos, mas o mais importante seria dar aos usuários uma dica errada. Basta pensar sobre que sentido porcaria que faria para dar std::iteratorum destrutor virtual.

Respondeu 09/12/2008 em 20:06
fonte usuário

votos
26

A questão é realmente, você quer impor regras sobre como deve ser usado suas aulas? Por quê? Se a classe não tem um destrutor virtual, qualquer um usando a classe sabe que não se destina a ser derivada de, e quais as limitações se aplicam se você tentar de qualquer maneira. Não é bom o suficiente?

Ou você precisa do compilador para lançar um erro difícil se alguém se atreve a fazer algo que você não tinha previsto?

Dê a classe um destrutor virtual, se você pretende para as pessoas a dela derivam. Caso contrário, não, e assumir que qualquer pessoa usando o seu código é suficientemente inteligente para usar seu código corretamente.

Respondeu 09/12/2008 em 20:18
fonte usuário

votos
8

Não! destruidores virtuais são utilizados apenas quando um objecto de uma classe de derivados é eliminado através de um ponteiro classe base. Se sua classe não se destina a servir como a base neste cenário, não fazem o processo de destruição virtual - você estaria enviando uma mensagem errada.

Respondeu 09/12/2008 em 20:04
fonte usuário

votos
4

Confira este artigo de Herb Sutter :

Orientação nº 4: Uma classe destructor base deve ser pública e virtual ou protegido e não virtual.

Respondeu 10/12/2008 em 14:08
fonte usuário

votos
2

Eu faria "não" à pergunta geral. Não cada classe precisa de um. Se você pode saber que a classe nunca deve ser herdada de, então não há necessidade de suportar a sobrecarga menor. Mas se há uma chance, estar no lado seguro e colocar um lá.

Respondeu 09/12/2008 em 19:58
fonte usuário

votos
0

classe base se torna classe abstrata, quando ele contém pelo menos uma função virtual pura. Se a base não tem um destrutor virtual e Derivados (derivado de base) faz, então você pode destruir com segurança um objeto Derivado através de um ponteiro de objeto Derivado mas não através de um ponteiro de objeto Base.

Respondeu 12/05/2010 em 21:04
fonte usuário

votos
0

Vou acrescentar que houve momentos em que me arranhou minha cabeça por um tempo em destruidores não ser chamados quando eu esqueci um virtual na classe pai ou filho. Eu acho que eu sei que olhar para isso agora embora. :)

Alguém pode argumentar que há momentos a classe pai faz algo em seu destruidor que uma criança não deve fazer ... mas isso é provavelmente um indicador de algo errado com a sua estrutura de herança de qualquer maneira.

Respondeu 09/12/2008 em 20:14
fonte usuário

votos
-3
include<iostream> using namespace std;

class base {
    public: base() {
        cout << "In base class constructor" << endl;
    }

    virtual ~base() {
        cout << "in base class destuctor" << endl;
    }
};

class derived : public base {
    public: derived() {
        cout << "in derived class constructor" << endl;
    }

    ~derived() {
        cout << "in derived class destructor" << endl;
    }
};

int main() {
    base *b; // pointer to the base
    class b = new derived; // creating the derived class object using new
    keyword;
    delete b;
    return 0;
}
Respondeu 01/01/2016 em 13:52
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more