2012-02-02 14 views
7

Devo dichiarare il metodo di finalizzazione finalize() per tutti i discendenti della classe base Base, che dovrebbe essere chiamato durante la distruzione, e il mio intento era di chiamare puro virtual void Base::finalize() = 0 dal ~Base(), ma C++ proibisce una cosa del genere. Quindi la mia domanda èChiamare il metodo virtuale dal distruttore - soluzione alternativa?

Come possiamo obbligare i discendenti di fare qualche lavoro di finalizzazione in modo giusto e definito preliminare?

Questo codice non può essere compilato:

#include <QDebug> 
class Base { 
     public: 
      Base(){} 
      virtual ~Base(){ 
       qDebug("deleting b"); 
       finalize(); 
      } 
      virtual void finalize() = 0; 

    }; 

class A : public Base 
    { 
    public: 
     A(){} 
     ~A(){} 
     void finalize(){qDebug("called finalize in a");} 
    }; 

    int main(int argc, char *argv[]) 
    { 
     Base *b = new A; 
     delete b; 
    } 

Se faccio Base::finalize() non virtuale pura, si chiama da ~Base() senza dispacciamento a figlio poiché è stato già distrutta.

posso chiamare finalizzare() dal distruttore del bambino ma domanda è come alla forza per farlo. In altre parole, la mia domanda è: è possibile obbligare le persone che scriveranno discendenti della classe Base a usare il metodo di finalizzazione, beh, in un altro modo che commentare in una documentazione? :)

risposta

7

distruttori sono il posto giusto per liberare risorse acquisite, ma ogni classe è responsabile di liberare le proprie risorse. Le risorse acquisite da class A non dovrebbero (e non possono) essere rilasciate da class Base.

Definizione distruttori virtuali permette class A 'distruttore s da chiamare quando si elimina un puntatore a class Base che punta a un oggetto class A

Base* p = new A; 
delete p; // Both A and Base destructors are sequencially called! 

Quindi, per ottenere il corretto rilascio delle risorse è sufficiente rilasciare ogni classe' risorse nella sua proprio distruttore.

+1

Ok, lo vedo, ma la mia domanda è: è possibile obbligare le persone che scriveranno i discendenti della classe Base ad usare il metodo di finalizzazione, beh, in un altro modo che commentarlo in una documentazione? :) –

+1

È possibile ma potresti ottenere errori di compilazione o di run-time, perché quando viene chiamato il distruttore di 'Base', il distruttore di' A' è già stato chiamato così non c'è alcun oggetto 'A' su cui chiamare il cosiddetto metodo 'finalize()'. –

+1

Ho usato il tuo codice di esempio e definito 'finalize()' per 'Base', rendendolo così semplice virtuale (non puro). Compilare, ma vedere cosa si ottiene dalla sua esecuzione http://ideone.com/opDXc –

3

Questo è ciò che un distruttore virtuale è per:

class A 
{ 
public: 
    virtual ~A() {} 
}; 

class B : public A 
{ 
public: 
    virtual ~B() {} 
}; 

Quando un oggetto di tipo B è distrutta, indipendentemente da un puntatore a una B o un puntatore a un A, entrambi distruttori saranno chiamato. Innanzitutto, B::~B() e poi A::~A().

+0

@DmitryKachko basta scrivere una chiamata a "unsubmit" in ogni distruttore in cui si desidera "unsubmit" per accadere –

+0

Certo che posso farlo, ma non posso obbligare le persone che useranno la classe A come base –

+0

Grazie per il vostro risposta! Come potrebbe aiutarmi? Ho annullato la funzione unsubmit() che dovrebbe essere chiamata in ciascuna delle discendenti di A durante la distruzione. L'implementazione dell'Inviamento è diversa per ognuno di essi. - –

1

rendere la classe distruttore di base pura virtuale con un corpo, che dovrebbe fare esattamente quello che vuoi.

+1

Perché virtuale puro? –

+0

Per forzare le classi derivate a dichiarare e implementare un proprio distruttore. –

+0

Oh, non ho visto che la base fosse astratta (forse una modifica successiva). –

0

Perché non utilizzare il decodificatore di Base? Quello per cui sono fatti i distruttori.

Ricerca per RAII e scoprire una delle più belle cose in C++.

La maggior parte delle persone utilizzato per utilizzare altre lingue devono scoprire questo. La gestione delle risorse in C++ è completamente diverso che in molti altri linguaggi di programmazione

+0

Che cosa ha a che fare RAII con la sua domanda? –

Problemi correlati