Newsgroup: it.comp.lang.c++
Titolo: costruttori, membri virtuali e ordine di inizializzazione

Ho una classe (base) che espone dei metodi protected virtual. Da questa
classe ne derivo una seconda (la derivo come virtual public) ma quando nel
costruttore della classe base chiamo i metodi virtuali vengono eseguiti
quelli della classe base anche se questi sono stati correttamente ridefiniti
nella classe derivata! mentre se chiamo tali metodi virtuali in qualsiasi
altro posto che non sia il costruttore della classe base, beh vengono
eseguiti quelli ridefiniti.
ma xche? io vorrei che anche nel costruttore venissero eseguiti quelli
ridefiniti, come si fa?
uso Microsoft Visual C++ 5.0 e le impostazioni del progetto sono quelle
standard (piů i link ad alcune librerie DirectX ma non dovrebbero centrare
niente spero!)
Magari č una specifica del linuaggio, il fatto che si debba comportare
cosě... ma spero di no, mi sembra un po incoerente....
C'`e un modo per aggirare sto problema?
Bye bye e grazie :)

 C'`e un modo per aggirare sto problema?
Parecchi, normalmente basati sull'idioma "two-phase
construct, two-phase destruct".
In questo idioma, i costruttori e i distruttori sono
basati sul concetto di *fare il minimo assoluto che sia
possibile* per mettere gli oggetti in uno stato *noto
e prevedibile* ma non ancora semanticamente corretto
(tale da soddisfare l'invariante).  Il ruolo di
"apparecchiare" l'oggetto in modo da soddisfare i suoi
invarianti semantici e` lasciato invece ad un metodo
"normale", spesso chiamato Create o Init o Construct.
In questo modo gli automatismi di ordinamento che il
compilatore ti garantisce per l'esecuzione dei vari
costruttori non sono piu` rilevanti e tocca invece a
te, come programmatore, scegliere l'ordine in cui
vanno eseguite le varie operazioni di "creazione",
nonche` la strategia con la quale potrai assicurare
la coerenza semantica dell'oggetto.  Ad esempio, puoi
porre una chiamata ad Init all'ingresso in ciascun
metodo, e rendere Init idempotente a fronte di multiple
chiamate (tipicamente aggiungendo allo stato dell'oggetto
un membro booleano "sono gia` stato inizializzato" che
il costruttore pone a false, Init verifica prima di
lavorare [non facendo nulla se e` gia` true] e pone
a true come parte del suo lavoro).
Oppure, idea generalmente migliore, puoi ricorrere
alla pattern "factory": gli oggetti non sono costruiti
semplicemente dichiarandoli (basta rendere non public
i loro costruttori e puoi impedire che cio` succeda)
ma solo da funzioni o classi con lo specifico ruolo di
"fabbrica" che tornano un puntatore (o smart ptr).
Queste possono ovviamente anche chiamare la Init dopo
avere costruito l'oggetto vero e proprio.
Le stesse considerazioni si applicano naturalmente
anche alla "distruzione" di oggetti cosi` costruiti.
Alex

grazie mille del chiarimento quasi quasi ci ero arrivato da solo parlando on
un amico
però non avevo afferato il fatto che se chiamassi i virtuari ridefiniti
troverebbero l'oggetto non ancora inizializzato.
ok molto bella lídea di classi "fabbricatrici" non sapevo nemmeno quella
cosa che nonmettendo il costruttore come public non viene chiamato
automaticamente al momento della costruzione dell'oggetto(ho capito bene?)
cmq forse adotterò un altra strategia ma per inizializzare le cose in modo
corretto...ma quella delle classi costruttrici mi piace sempre di più.
grazie mille come sempre sei stato utilissimo, e anche velocissimo!!
bye bye

così... ma spero di no, mi sembra un po incoerente....
Sarebbe incoerente il contrario...
Paolo
--------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
--------------------------------------------------

 grazie mille come sempre sei stato utilissimo, e anche velocissimo!!
Prego!
Alex

cavolo
ho appena letto il pst sull pattern factory io non ho fatto tutto sto
casino!
:(sono un po rattristato
mi viene in mente che l'unico modo che ho per deallocare lóggetto è delete
puntatore
cavoloz
hei hei ma posso sovraccaricare il new?
in modo che agisca un po come funzione di inizializzazione (prima alloca poi
chiama l'evento di inizializzazione e poi ritorna il puntatore)? è una
pessima idea?che problmei comporterebbe? forse si finisce in un circolo
vizioso dato che all'interno della new dovrei cmq usare un altra new che in
questo caso è quella predefinita(sempre ammesso che new sia
sovraccaricabile)?
ok ciao ciao

sovraccaricabile)?
No... tutto sommato e` normale richiamare la new di default, anche se
di solito si ridefinire la new solo per utilizzare una diversa strategia
di allocazione.


 l'inizializzazione e` un compito da costruttore.
Considerazione sacrosanta.  operator new deve comunque tornare
sempre e solo (il puntatore a) "un blobbo di tot byte di memoria".
Alex

Perche` no?  Oltre a ridefinirlo, si puo` *anche* sovraccaricarlo.
Si, hai ragione... intendevo dire che non puoi inventarti un nuovo
prototipo per l'operatore. Puoi in sostanza ridefinire solo le
forme previste.
