Newsgroup: it.comp.lang.c++
Titolo: Funzioni virtuali chiamate dall'interno di una classe

Ciao!
Sto tentando di risolvere il seguente problema: ho una classe base di oggetti,
detta A, che durante la loro distruzione devono eseguire una funzione clean,
diversa per ogni classe figla B, C o D.
Ho quindi scritto:
class A
{
    ~A() {
        clean;
    }
    virtual void clean() = 0;
}
E quindi le classi figlie:
class B: A
{
    virtual void clean() {
        ...
    }
}
class C: A
{
    virtual void clean() {
        ...
    }
}
class D: A
{
    virtual void clean() {
        ...
    }
}
Speravo che poteva venirmi in aiuto il polimorfismo, in quanto se faccio:
A* ptr;
...
ptr->clean();
Viene ovviamente eseguito il clean giusto, rispetto a cosa punta ptr. Pensavo
che il compilatore incontrando, all'interno del distruttore, this->clean()
creasse una chiamata di funzione "intelligente", ma a runtime mi viene detto
"STOP! Hai chiamato una funzione pura", ovvero viene chiamata A::clean(), non
implementata.
In realtą l'esempio č fin troppo semplificato, vorrei mettere clean nel
distruttore della classe base poichč ci sono delle condizioni comuni a tutte
le classi per capire se eseguire clean oppure no, quindi volevo percorrere
questa via invece che inserire la chiamata di clean (di per se complessa) in
ogni distruttore di B, C, D.
Chi mi aiuta?
Stefano Pettini
Notary of 
www.thawte.com

 snip
Ciao Stefano,
a quanto ne so e´ un bel dilemma.
In quanto in fase di distruzione dell´oggetto di classe base A, sono gia´
stati distrutti gli oggetti delle classi derivate che ereditano da A, per
cui non puoi usare l´override in fase di distruzione dell´oggetto di tipo A.
Alternative?
...Ci sto pensando!
Maurus

 implementata.
Il problema te l'ha gia' descritto Maurus. Vedo due strade per
risolverlo. O sposti tutta la parte comune da "ripulire" nella classe
base ed esegui la pulizia nel distruttore della medesima, o definisci
una funzione membro protected nella classe base in cui esegui la parte
comune di pulizia, e la richiami in ciascun distruttore delle classi
figlie.
Ciao,
Nicola

}
...
Due appunti.
1) il distruttore che hai dichiarato non e' virtuale... se
   tu chiami "delete p" dove p ha come tipo "puntatore a base"
   e invece sta puntando ad un oggetto derivato allora sconfini
   nell'undefined behaviour.
   Se una classe e' pensata per essere base di derivazione
   (come ovviamente le ABC) allora il distrutture dovrebbe
   essere sempre dichiarato virtuale per evitare di fare
   queste sviste.
2) Quando viene eseguito il distruttore di una classe base
   in ogni caso l'oggetto in fase di distruzione non e' piu'
   di tipo "derivato". Infatti la parte di distruzione
   "derivata" e' gia' stata eseguita e i membri presenti in
   derivata ma non in base sono in seguito stati distrutti
   automaticamente prima di entrare nel distruttore di base.
   Eseguire una funzione virtuale della derivata su un simile
   "zombie" sarebbe privo di senso: la parte derivata e' gia'
   morta. La situazione e' analoga a quanto accade nei
   costruttori: se chiami una funzione virtuale nel costruttore
   della parte base durante la costruzione di un oggetto derivato
   che fa l'override della funzione questo override non viene
   attivato. Il motivo in questo caso e' che la parte "derivata"
   deve ancora essere costruita... chiamare un metodo su un
   oggetto in cui non e' ancora stato eseguito il costruttore
   sarebbe senza senso.
   Nota che in altri linguaggi OO si sono fatte scelte diverse
   su questo punto.
Per fare quello che chiedi credo sia necessario chiamare
clean() nel distruttore di ciascuna classe derivata... se da
questo distruttore chiami un metodo di base allora in quel
metodo le chiamate virtuali funzionano correttamente perche'
l'oggetto che e' in fase di distruzione e' il derivato.
Spero di non aver aumentato la confusione :)
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

Per il distruttore virual ok, li metto sempre virtual, mi sono dimenticato di
scriverlo. Seguirò il vostro consiglio di mettere il più possibile nella
classe base, e la sola chiamata polimorfica nelle classi figlie.
--


le classi
Questa sinceramente mi pare una pessima idea, specie se le classi
derivate dichiarano nuovi membri che devono poi essere distrutti.
Il Ghenio
-----
ZIO : Fun and games are over with. Anyone who dares
get in my way shall perish.
-----