Newsgroup: it.comp.lang.c++
Titolo: Costruttori inguaiati

Un costruttore non ritorna valori, per cui se il costruttore vede che 
"non ce la fa" e la costruzione dell'oggetto fallisce, come fa ad 
avvertire il chiamante dell'increscioso fatto??
1) Faccio sollevare un'eccezione dal costruttore? Ma mi conviene??
2) Implemento un metodo bool OggettoOK() nell'oggetto, cosě posso 
testarlo subito dopo la creazione per vedere se č stato creato bene 
oppure no?
Voi come fate di solito, e perché?

 testarlo subito dopo la creazione per vedere se è stato creato bene


 Solo alla fine del costruttore metto a true quel segnalino bool.
Sistema interessante, non ci avevo pensato :-)
Il problema mi si poneva non nel caso di ram esaurita, errori di I/O o 
altre catastrofi, ma più modestamente della validità dei dati da passare 
al costruttore: l'oggetto ha senso solo se i dati sono appropriati, 
altrimenti costruirlo porterebbe ad errori successivamente. La 
validazione dei dati al momento della costruzione dell'oggetto sarebbe 
perfetta al mio scopo, ma se il costruttore "non può fallire"... non si 
può fare, almeno non direttamente.
Per cui avevo pensato di rendere privato il costruttore e creare una 
classe factory (o magari una semplice funzione friend) che prima testa i 
dati e poi, se vanno bene, chiama il costruttore.
Così dovrebbe andare bene: sarebbe una specie di "costruttore esterno".

 Cos dovrebbe andare bene: sarebbe una specie di "costruttore esterno".
Allora potresti pensare ad un metodo bool
tuoOggetto::initWithValues(...) che prova ad inizializzare un oggetto
con i parametri che gli passi.
Se la validazione passa, il chiamante sa di poter contare
sull'oggetto, altrimenti nisba e magari lo elimina o non lo utilizza
affatto.
A questo punto il costruttore deve solo preoccuparsi di settare lo
stato iniziale delle variabili interne, allocare memoria per qualche
buffer, insomma preparare l'oggetto per essere utilizzato (e quindi
dovrebbe fallire SOLO in caso delle catastrofi sopraccitate).
Una volta allocato l'oggetto, richiami il tuo metodo
initWithValues(...) e controlli il valore di ritorno.
Chiaro che questo metodo deve settare una qualche variabile interna su
true nel momento in cui l'inizializzazione va a buon fine, onde
evitare successive inizializzazioni che per logica non dovrebbero
poter avvenire.
Comumque, guardandola sotto questo aspetto, è una soluzione vicina
alla tua tranne per il fatto che l'inizializzazione non può essere
chiamata al momento della creazione dell'oggetto ma solo
successivamente (al contrario del costruttore).

 Voi come fate di solito, e perché?
Usa sicuramente un sollevamento di eccezione

 E' difficile eventualmente gestire una eccezione ?
Il punto è che... cosa la fai a fare un'eccezione? Il punto di ritorno 
dell'eccezione è fuori dal blocco try, ma il codice dopo il try deve 
comunque testare se l'oggetto è stato creato oppure no, al limite 
testando un bool settato dal codice nel catch. Ma a questo punto che 
cosa ci ho guadagnato a lanciare un'eccezione?
Pensa e ripensa mi pare che il controllo sui dati deve essere fatto per 
forza esternamente al costruttore e non dentro il costruttore stesso, 
perché non c'è modo di farlo fallire e quindi non c'è modo di evitare di 
dover controllare se l'oggetto creato è valido, o prima di crearlo 
oppure dopo averlo creato.
Insomma nel caso di oggetti complessi, che devono godere anche di una 
coerenza interna, mi pare che non ci sia alternativa: vanno costruiti E 
ANCHE validati, ma le due fasi non possono svolgersi contemporaneamente.

 affatto.
Sì, la costruzione/inizializzazione potrebbe essere un'altra idea.
Magari, per maggior sicurezza, si potrebbe fare in modo che tutti gli 
altri metodi falliscano lanciando un'eccezione (che stavolta sarebbe 
giustificata), se vengono invocati prima dell'inizializzatore: le prime 
istruzioni di ogni metodo dovrebbero essere del tipo
if(!InitOK)
	throw(__KABOOM__);

 ANCHE validati, ma le due fasi non possono svolgersi contemporaneamente.
Un oggetto appena costruito deve anche essere in uno stato valido, se 
non lo è esiste qualche cosa che non va nella progettazione della classe.

Eccezione sollevata dal costruttore.
Ti consiglio di leggere "exeptional C++" il quale dedica una parte proprio a questo.
Ciao.
Il 17/03/2011 16:04, Massimo Soricetti ha scritto:
