Newsgroup: it.comp.lang.c++
Titolo: Eccezioni e scope

Ho una classe con un costruttore che può sollevare eccezioni. Quando
creo sullo stack un oggetto di quella classe devo (inevitabilmente?)
catturare l'eccezione in questo modo:
try {
	Date d;
} catch (...) { }
d.set_year();	// d non dichiarato in questo scope
Il problema è che nel codice seguente il try... catch non posso usare
"d" in quanto out of scope. Come posso fare? Vorrei evitare le
seguenti soluzioni, se possibile:
1) usare puntatori e allocare con new (come in Java)
2) mettere il catch dopo TUTTO il codice seguente (argh!)
Grazie per le risposte.

 2) mettere il catch dopo TUTTO il codice seguente (argh!)
se sei sicuro che il costruttore di Date non possa sollevare eccezioni,
dichiara Date prima del try...catch:
Date d;
try { ... } catch(...) { ... }
d.set_year();
altrimenti per forza con new.
p.s.:per quale motivo non vuoi usare new?
--
ciao
xaero

d.set_year();	// d non dichiarato in questo scope
A parte il problema di essere fuori dallo scope c'e' anche un
problema logico. Se il costruttore di Date genera una exception
l'oggetto d non e' stato costruito e ovviamente non ha senso
cercare di utilizzarlo chiamando d.set_year().
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff


La try/catch non deve essere necessariamente circoscritta
all'istanziazione
di d. Puoi dare alla try-catch uno scope piu largo, inserendovi
all'interno 
tutte le operazioni che devi fare su d.
Qualcosa come
try {
	Date d;
	...
	// se passi da qui sei tranquillo:
	// tutto e' andato liscio
	...
	...
	d.set_year()
	...
	...
	// quando d non ti serve piu'...
	...
} catch(...) { /* qui devi fare qualcosa */}
Spesso, potrebbe essere ancora meglio gestire le eccezioni nella
funzione chiamante
o in quella prima ancora...dipende dalle situazioni e da cosa puoi fare
quando
si verifica un'eccezione.
Non capisco perche' questa soluzione non ti piace. Le eccezioni hanno
questo 
vantaggio rispetto alla tecnica "tradizionale" del ritorno di codici
d'errore:
che puoi gestire l'eccezione a livelli superiori rispetto al punto in
cui si e'
verificata. Questo ti permette di gestire gli errori in un contesto piu'
ampio,
o di gestire lo stesso errore nella maniera piu' appropriata a seconda
del 
contesto in cui si e' verificata....
La grande idea dietro le eccezioni e' quella di potere gestire a un
certo livello
degli errori che possono verificarsi a livelli piu bassi.
Se si dovesse circondare con una try/catch ogni istruzione che puo'
generare
un'eccezione sarebbe un disastro. 
Purtroppo questa e' una cosa che ho visto spesso in programmi in Java,
(e di
riflesso, anche in programmi C++ scritti da 'javaroli') 
Credo che il problema di Java (riguardo alle eccezioni) e' che i metodi
devono
dichiarare esplicitamente le eccezioni che possono lanciare. 
Quindi, per non dichiarare una sfilza di eccezioni per ogni metodo,
molti circondano
le espressioni "pericolose" con delle try/catch che, spesso e
volentieri, hanno
un corpo vuoto (come nell'esempio postato) perche', a quel livello non
si e'
in grado di gestire l'eccezione opportunamente (dopo tutto ci troviamo
quasi 
allo stesso livello in cui l'eccezione e' stata lanciata, e se fossimo
in grado
di gestirla correttamente, non ci sarebbe stato neanche bisogno di
lanciarla ;-).
Cosi si finisce col rendere inutile e contro-producente questo
meccanismo
(magari invece una try/catch in uno dei livelli superiori avrebbe
informazioni di
contesto sufficienti e gestire l'eccezione correttamente)
Ricorda comunque che usare le eccezioni richiede molta attenzione e
scrivere
del codice veramente exception-safe e' un'impresa molto difficile.
(a questo proposito ti rimando, ad esempio, all'ottimo libro
"Exceptional C++"
di Herb Sutter, Addison Wesley, 1999)
Saluti,
Fabio
-- 
Posted from [194.214.173.28] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG


Ma leggi:
    "Ho una classe con un costruttore che può sollevare eccezioni"
.
-- 


 Grazie per le risposte.
Non capisco che problema hai a usare la tecnica 1 o 2.
Non dirmi "leggibilita'".
---
Gaetano.


     "Ho una classe con un costruttore che può sollevare eccezioni"
whoooops! :-)
allora non c'è nessuna soluzione possibile escludendo quelle menzionate da
gem...
--
ciao
xaero

Non dirmi "leggibilita'".
try {
1) Dovrei poi mettere un delete ad ogni possibile uscita dalla
funzione (o usare RAII (Resource Acquisition...). In entrambi i casi
mi sembra uno sforzo eccessivo, dato che il mio intento iniziale era
semplicemente quello di creare un oggetto sullo stack e catturare una
eccezione nel caso venisse sollevata... è proprio necessario
complicare le cose così tanto per fare una cosa (in teoria) tanto
semplice?
2) IMHO, racchiudere molto codice in un try...catch ha due svantaggi:
2.1) Indenti molto codice che non avrebbe in teoria bisogno di
indentazione (e magari in casi patologici devi pure annidare un try...
catch dentro l'altro arrivando a indentazioni da guinness)
2.2) Se all'interno del try... catch creo più di un oggetto (o viene
sollevato lo stesso tipo di eccezione in un metodo, ecc.) devo
aggiungere altra complessità per capire quale degli oggetti ha causato
l'eccezione
} catch (TroppoPignoloException e) {
	std::cerr << "Vabbe', metto la new... uff!!!" << '\n';		
	exit(1);
}

Credo che ti convenga abituarti, perche' non esiste altro modo di
scrivere codice solido in C++. Almeno noi abbiamo l'idiom RAII, che ci
permette di limitare i try/catch allo stretto necessario...
Ciao,
Nicola