Newsgroup: it.comp.lang.c++
Titolo: void *, new e delete?

Salve a tutti, mi e' venuto un dubbio, vorrei 
delucidazioni su cosa dice lo standard C++ sulla cosa.
Il codice seguente che cosa fa?
// Creo puntatore ad un oggetto
void *p = new CString;
// Dealloco ???
delete p;
... cioe' la delete di 'p' cancella solo l'area di
memoria o anche l'oggetto (chiamando il distruttore).
Ho provato a scrivere il codice col compilatore IBM
sotto OS/2 e sembra che senza un cast la delete del
puntatore void non chiami il distruttore dell'oggetto,
non so dire per quanto riguarda la memoria se viene
deallocata o meno.
La domanda e' cosa accade per lo standard C++
se dealloco un puntatore a void tramite delete?
Grazie in anticipo.


ICQ #34602650

 ICQ #34602650
Ciao
*Fabio*

 memoria o anche l'oggetto (chiamando il distruttore).
La memoria viene rilasciata; ma non viene chiamato il distruttore
della classe CString: viene chiamato il distruttore degli oggetti
di tipo void --- che non fa nulla.  "p" e' un pointer generico; il
compilatore non ha nessun modo di associare la memoria puntata con
l'appartenenza dell'oggetto contenuto ad una classe.
Pensa un poco: se tu scrivessi
std::cout << *p << std::endl;
il compilatore darebbe errore, e per lo stesso motivo: non ha idea di
come tradurre in simboli leggibili il contenuto di *p.
Insomma: Se un oggetto e' un'istanza di una CString, utilizza come
puntatore una variabile di tipo (CString *): perche' fare altrimenti?
Al limite scrivi (untested ...):
delete static_cast<CString *>( p );
e ricordati che ogni cast e' sintomo di cattivo design :-)
-- 
Maurizio Loreti                      
http://wwwcdf.pd.infn.it/~loreti/mlo.html
Un. of Padova, Dept. of Physics - Padova, Italy          
lor...@padova.infn.it

Questo dal punto di vista "teorico".
Premesso che le classi del tuo esempio non sono l'una derivata
dall'altra e questo potrebbe comportare non pochi problemi...
Il punto comunque non e` il fatto che il distruttore non fosse virtual
(il virtual serve solo se lavori con oggetti polimorfi), ma che il
puntatore a CString ottenuto da new veniva convertito a void*
e il tipo void* non ha alcun distruttore associato.
Paolo
-----------------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
-----------------------------------------------------------------

 (il virtual serve solo se lavori con oggetti polimorfi), 
Beh, nel caso del distruttore è un discorso leggermente più delicato.
Supponiamo l'esempio (questa volta più pulito :-)):
class a {
public:
	a() {};
	virtual ~a() { printf("Distruttore a\n");};
};
class b :public a {
public:
	b() {};
	virtual ~b() { printf("Distruttore b\n");};
};
int main()
{
	a * ptr = (a*)new b;
	delete ptr;
	return 0;
}
Se i distruttori sono virtual, vengono chiamati entrambi altrimenti il
costruttore b non viene proprio chiamato.
Il distruttore è un caso un po' particolare.


 costruttore b non viene proprio chiamato.
  ^^^^^^^^^^^
Distruttore.
EMG

Il distruttore è un caso un po' particolare.
Ma guarda che il tuo  e` proprio un caso di uso di oggetti polimorfi!
Nel contesto del C++ si parla di oggetti polimorfi quando hai una gerarchia di
classi e le loro istanze vengono utilizzate tramite puntatori a classe base.
Se tu avessi fatto a meno dei puntatori, cioe` scritto
b bOgj;
oppure evitato di utilizzare puntatori a classe base per
puntare a oggetti di classe derivata (responsabilita`
del programmatore):
b* ptr = new b;
allora il virtual nel distruttore sarebbe inutile.
Molti testi consigliano l'uso di virtual in ogni classe che possa
potenzialmente essere derivata, quello che non viene detto e` 
che tale consiglio ha a monte l'assunzione che il programma 
utilizzi gli oggetti tramite puntatori a classe base, e tale
assunzione non e` sempre verificata.
E` vero tuttavia che a priori non sapendo come verra` utilizzata
la gerarchia e` comunque bene seguire il consiglio, anche perche`
quando possibile il compilatore cerca di risolvere subito il
binding.
Un'altra cosa... il cast esplicito nella new non e` necessario.
