Newsgroup: it.comp.lang.c++
Titolo: eccezioni e contestualizzazione dell'errore

ho letto qualche giorno fa un msg sul confronto fra eccezioni e utilizzo
massiccio dell'if per gestire gli errori. personalmente preferisco il primo
metodo pero' ho un problema.
quando viene lanciata un'eccezione, per segnalare un errore, l'oggetto
lanciato dovrebbe contenere quante + informazioni possibili sull'errore
verificatosi (direi anche se e' troppo forte "a qualsiasi costo" in termini
di complessita' e di risorse, tanto la gestione dell'errore e' una cosa in
teoria "eccezionale")
talvolta la funzione che lancia l'eccezione pero' non ha informazioni
sufficienti sul contesto nel quale si e' verificato l'errore. per
"caratterizzare" maggiormente l'errore quindi sarei tentato di usare
try-catch in questo modo
try
{
    fa' quel che devi fare
}
catch (errore e)
{
    // metti in e informazioni circa il contesto e rilancialo
}
questa situazione mi si e' presentata scrivendo un interprete, in cui una
"funzione primitiva" genera un'eccezione, ma non sa a che punto del
programma si e' fermata l'esecuzione. l'interprete si' pero', pero' non e'
compito dell'interprete visualizzare/mostrare all'utente l'errore, in quanto
la classe interprete e' riusabile in svariati ambienti: l'interprete si
limita a lasciar passare l'eccezione a chi l'ha usato. pero' deve fornire
qualche informazione utile quindi e' costretto a bloccare l'eccezione come
fatto sopra.
morale? morale il codice finisce per assomigliare in maniera impressionante
al metodo if, cioe'
if ( ... fa' quel che devi fare... )
{
}
else
    // caratterizza l'errore e return errore
dunque? uno che fa? usa ugualmente le eccezioni? oppure questo e' uno di
quei casi in cui e' preferibile usare il "vecchio" if?
bye
Simone

 quei casi in cui e' preferibile usare il "vecchio" if?
Io uso spesso questo secondo metodo quando una serie di operazioni devono 
andare a buon fine prima di poter 'generare' il risultato 
dell'elaborazione e mi trovo molto bene.
In altri casi (più semplici) uso try...catch()
-- 
Luc.

 di quei casi in cui e' preferibile usare il "vecchio" if?
io uso il re-throw, un esempio:
try
{
 funzione_delicata();
}
catch(errore& e) 
{
 if (!posso_gestire_qui()) 
 {
   fai_qualcosa_ad(e);
   throw;
 }
 else
   fai_quel_che_puoi();
}
in pratica, supponendo che quello sopra sia il codice dell'interprete, 
lo chiamo cosi'
try {
 interprete.eval(stringa);
}
catch (errore& e)
{
  // ops, se arrivo qui, l'interprete mi ha rilanciato un'eccezione
  if( posso_gestire(e) )
  {
    stampa_info(e);
  }
  else
    distruggi_il_sistema(); 
    /* fa esplodere il pc di un utente cosi' maleducato da causare 
       un'eccezione non gestibile */
}

 try-catch in questo modo
Fai un esempio ?
Ciao
Gaetano.
-- 
Posted from 
nts-03.mm.eutelsat.org
 [194.214.173.15] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

Definisci una bella classe, che eredita dalle eccezioni standard e che
contenga quel qualcosa in piu' che ti serve per identificare cosa e'
successo e dove; ad esempio (codice non testato):
struct myException : public runtime_error {
  enum ERROR_TYPE { GRAMMATICA, SINTASSI, LOGICA, BOH };
  ERROR_TYPE flag;
  myException(const string & s, ERROR_TYPE e = BOH)
    : runtime_error(s), flag(e) {}
};
try {
  ...
} catch (myException & e) {
  cout << "Cosa mia: " << e.what() << ", errore ";
  switch (e.flag) {
    case myException::GRAMMATICA: cout << "grammaticale\n"; break;
    case myException::SINTASSI:   cout << "sintattico\n";   break;
    case myException::LOGICA:     cout << "logico\n";       break;
    default:                      cout << "Can't happen!";
  }
} catch (exception & e) {
  cout << "Eccezione standard: " << e.what() << endl;
} catch (...) {
  cout << "Aiuto!  Cosa succede?\n";
}
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it

 }
Ciao,
Nicola

fatto sopra.
Considera che hai la possibilità di usare qualsiasi tipo di classe da
lanciare come eccezione, e puoi creartene una apposita dove ci metti
tutte le informazioni possibili per gestire i tuoi errori.
A questo punto puoi analizzare l'eccezione direttamente nel blocco
catch e valutare se può essere gestita subito oppure rilanciata ad un
altro exception-handler tramite throw.
Ti sconsiglio di usare il blocco di if.
Il Ghenio
-----
These are my parting words to you:
those who give up are doomed!
-----

In effetti possono esserci situazioni in cui il codice di gestione degli
errori tramite eccezioni assomiglia a corrispondente codice che gestisce
gli errori tramite codice numerico.
Le differenze pero' sono fondamentali: con le eccezioni non puoi fare a
meno di compiere una scelta consapevole ad ogni livello (ovvero in ogni
funzione attiva) riguardo al gestire o meno l'eccezione in quel punto,
mentre con i codici di errore puoi sempre scegliere di ignorarli.
Se scegli di ignorare l'eccezione non devi fare nulla (*), perche' e'
automaticamente propagata al livello superiore, mentre il codice di
errore devi propagarlo esplicitamente.
Con le eccezioni puoi trasportare informazioni relative al contesto
dell'errore, mentre con i codici di errore devi renderle disponibili con
un meccanismo specifico.
A me pare che basti...
Ciao,
Nicola
(*) non e' del tutto vero, perche' devi comunque fare attenzione a
ripulire lo stato locale.