Newsgroup: it.comp.lang.c++
Titolo: Distruttori.

Forse mi sto perdendo in un bicchiere d'acqua.
Ho una classe, chiamiamola "corpo celeste", che definisce un generico 
oggetto presente nello spazio.
Ha alcune proprieta', quali ad esempio le coordinate nello spazio ed il 
nome.
Per ora non ha bisogno di un distruttore generico.
Dopodiche' ho chiamato una classe "pianeta", estensione della classe 
"corpo celeste", alla quale ho aggiunto una serie di dati aggiuntivi, 
tipo raggio, orbita, la mesh sferica che mi rappresenta il pianeta, e 
le texture che lo rappresentano.
In questo caso mi serve ovviamente definire un distruttore per la 
classe "pianeta", che quando agisce deve deallocare la mesh e la 
texture.
Infine ho una terza classe, chiamiamola "lista corpi", che e' appunto 
una lista di oggetti celesti, siano essi pianeti o altro.
In questo caso occorrera' un distruttore che, per ogni oggetto presente 
nella lista, vada a chiamare il distruttore corrispondente.
E qui iniziano i dolori.. dal momento che la lista, per poter contenere 
i vari tipi di corpi celesti, dev'essere di tipo generico "corpo 
celeste".
Quando scorro la lista, al suo interno trovo solo puntatori della 
classe generica, che, ricordiamolo, non ha nessun distruttore. Quindi 
se trovo un oggetto di tipo "pianeta", questo viene in realta' 
considerato di tipo "corpo celeste", e non viene lanciato il 
corrispondente distruttore, lasciandomi mesh e texture allocate.
Nello specifico:
Body = Classe corpo celeste generica
CelestialBody = Classe pianeta, con mesh e texture
BodyCollection = Lista di corpi celesti (siano essi generici o pianeti 
o altro che in futuro dovro' implementare)
Definizione della lista di "corpi celesti":
vector<Body*> collection;
Costruttore di BodyCollection:
// crea un pianeta, con texture e mesh
CelestialBody* star = new 
CelestialBody("Sun",0,0,0,696000.0,TRUE,FALSE,&mStarMtrl,"gstar.jpg",pD3dDevice,pFX);
collection.push_back(star);
Distruttore di BodyCollection:
BodyCollection::~BodyCollection() {
	vector <Body*>::iterator bodyIter;
	for ( bodyIter = collection.begin( ) ; bodyIter != collection.end( ) ; 
bodyIter++ )
	{
		Body* b = *bodyIter;
		delete b;
	}
}
La linea "delete b" ovviamente invoca il distruttore della classe 
"corpo celeste", non si accorge che nello specifico dentro alla lista 
c'e' un pianeta, derivato da "Body", e non chiama il distruttore 
specifico.
Ci vorrebbe una delete intelligente in grado di capire se l'oggetto 
della lista e' un'estensione della classe Body, richiamandone cosi' il 
distruttore appropriato.
Son poco pratico di c++ ma mi sto un po' incasinando.. come risolvo la 
faccenda?

 vector<Body*> collection;
nella definizione di Body aggiungi:
virtual ~Body() {}
L'esistenza di un distruttore virtuale dice di fatto al compilatore di 
chiamare per ogni oggetto il suo specifico distruttore.
Anche la delete di un puntatore all'oggetto base in questo modo 
chiamera' i distruttori di eventuali classi derivate.
Visto il numero di errori che causa questo behaviour il GCC4 ad esempio 
da un warning se trova una situazione del genere (ma solo con -Wall)!
--
Bye,
  Gabry

 distruttore appropriato.
...
Si chiamano funzioni virtuali.
Definisci nella classe base un distruttore virtuale vuoto.
GM

GM ha detto questo lunedì :

Ok, ho risolto... vi ringrazio entrambi.
Giusto per capire cosa ho fatto :), cos'e' di preciso una funzione 
virtuale?

 
In due parole:
http://it.wikipedia.org/wiki/Funzione_virtuale
ma mi sa che se vuoi andare oltre ti conviene studiare un po di c++...
questi argomenti sono veramente ma veramente base!
GM

virtuale?
Ahem... forse č meglio se ti procuri un buon manuale di C++ ;-)

 
http://it.wikipedia.org/wiki/Funzione_virtuale
Grazie, poi avevo trovato da me.