PDA

Visualizza la versione completa : [C++] Ridefinizione distruttore


Dedalo_shares
12-01-2010, 23:13
Salve a tutti,
su consiglio di un amico, vi sottopongo una questione di natura più "concettuale" che tecnica, riguardante l'uso dei distruttori in C++ sotto certe condizioni.

In pratica, stando a quel che ho appreso durante il mio breve apprendistato sul C++, i costruttori e distruttori di una classe derivata non vengono naturalmente ereditati dalla/e classe/i base per cui occorre sempre definire costruttori e distruttori per tutte le classi di un programma.

Inoltre, sempre secondo le mie conoscenze, i distruttori delle classi, sono richiamati in ordine inverso rispetto a quello di derivazione, ossia un oggetto della classe "DERIVED" - derivata da "BASE" - richiamerà per primo il distruttore della classe "DERIVED", quindi quello di "BASE".

Fatte queste premesse, se avessi la necessità di adoperare un distruttore che svolga esattamente le stesse operazioni per "DERIVED" e "BASE" non risulterebbe inutile - oltre che potenzialmente pericoloso - ridefinire il distruttore di "DERIVED" dal momento che sarà comunque richiamato quello di "BASE" ?

shodan
12-01-2010, 23:33
In linea generale ereditare da una classe base senza distruttore virtual può avere comportamento indefinito.
http://www.eptacom.net/pubblicazioni/pub_it/iso_8.html
( le prime due affermazioni ).

Il problema che poni, come al solito ha una sola risposta: dipende.
La classe base molte vole è una classe vuota da cui si eredita solo il distruttore virtuale per implemetare una gerarchia di oggetti. In altri casi il costruttore della classe base alloca memoria (perché in fondo è questo il problema: la doppia cancellazione di un puntatore.)
Anche qui in linea generale ogni distruttore gestisce le risorse della sua specifica classe e niente altro.
Es:


class Base {
public:
Base () : p(new Tipo) {}
virtual ~Base() { delete p; }
protected:
Tipo* p;
};

class Derived : public Base {
public:
Derived () : ptr(new Tipo2) {}
~Derived () { delete ptr; }
protected:
Tipo2* ptr;
};

Però occorre considerare caso per caso e vedere la classe cosa fa esattamente.
Se il distruttore della classe derivata deve fare esattamente le stesse operazioni della classe base, si può anche omettere.
(Sempre in linea generale).

MacApp
13-01-2010, 03:26
Originariamente inviato da Dedalo_shares
Salve a tutti,
su consiglio di un amico, vi sottopongo una questione di natura più "concettuale" che tecnica, riguardante l'uso dei distruttori in C++ sotto certe condizioni.

Capire il funzionamento dei distruttori in C++ è essenziale, fondamentale, anche e soprattutto in relazione ad altri linguaggi. In C++ i distruttori sono un arma nelle mani del programmatore potentissima. Ma come al solito, le armi potentissime bisogna saperle usare.
Il tuo proposito, mi pare d'aver intuito, di condividere codice appartenente alla gerarchia stessa, in una gerarchia di classi, tra i vari distruttori, come anche nei costruttori, è in genere deleteria.
Per un essenziale motivo:


in C++, al contrario di altri linguaggi, sia nel costruttore, che nei distruttori, il meccanismo virtuale
giustamente non funziona!

Ad una prima lettura la precedente, potrebbe essere scambiata per una debolezza del C++ rispetto ad altri linguaggi, ma in effetti è il suo vero valore aggiunto, la sua vera POTENZA, anche solo a livello semantico, indipendentemente dall'efficienza prestazionale del codice eseguibile prodotto.

Sbagli quando affermi:

Originariamente inviato da Dedalo_shares
In pratica, stando a quel che ho appreso durante il mio breve apprendistato sul C++, i costruttori e distruttori di una classe derivata non vengono naturalmente ereditati dalla/e classe/i base per cui occorre sempre definire costruttori e distruttori per tutte le classi di un programma.

infatti dipende, come ti ha accennato shodan, dal contesto; dal programmatore!

In ogni modo, per farla breve, sempre ricordandosi che nei distruttori e ne costruttori il meccanismo virtuale giustamente non funziona, un modo abbastanza semplice per evitare mal di testa futuri, è quello di dichiarare SEMPRE i distruttori virtual.
;-)

XWolverineX
13-01-2010, 08:59
Originariamente inviato da MacApp
In ogni modo, per farla breve, sempre ricordandosi che nei distruttori e ne costruttori il meccanismo virtuale giustamente non funziona, un modo abbastanza semplice per evitare mal di testa futuri, è quello di dichiarare SEMPRE i distruttori virtual.
;-)

O comunque, ogni distruttore della classe derivata, distrugge solo ed esclusivamente i suoi dati.
Non la vedo così tragica, io.

Dedalo_shares
13-01-2010, 10:00
A essere sincero non mi aspettavo risposte così di qualità e devo dire, istruttive.
Vi ringrazio molto.

L'idea del distruttore virtual mi era in effetti, già venuta.
Tuttavia sinceramente ero infastidito dal fatto di dover riscrivere esattamente le stesse operazioni per un distruttore già definito e di non poter riutilizzare il codice, cosa che mi pareva una delle più importanti possibilità offerte dal C++.

Questo comunque mi da la dimensione di quanto ancora c'è da imparare :).

Loading