Salve a tutti....
Sto programmando in C++ e devo gestire una marea di situazioni di errore. Volevo un parere, mi conviene fare tanti if (.....) allora ..... oppure utilizzare le eccezioni try throw catch ?...
Perchè?
Grazie saluti
Salve a tutti....
Sto programmando in C++ e devo gestire una marea di situazioni di errore. Volevo un parere, mi conviene fare tanti if (.....) allora ..... oppure utilizzare le eccezioni try throw catch ?...
Perchè?
Grazie saluti
Non c'è una risposta assoluta. Le eccezioni sono uno strumento potente ma vanno usate con parsimonia e solo quando ci si può aspettare un comportamento inatteso del programma.
Per esempio una mancata allocazione di memoria (che già l'operatore new lancia) oppure il superamento di un limite di un array.
Se poi non si fa uso di smart pointer (o meglio del paradigma RAAI) la faccenda si complica perché occorre intercettare il throw, chiudere la risorsa acquisita e rilanciare un nuovo throw.
Per farla breve, dipende dal codice.
Idealmente:
- tutti gli errori trasformali in eccezioni (derivate, direttamente o no, da std::exception);
- cattura solo ad altissimo livello: ad esempio nella main, nei gestori d'eventi dei vari framework, nei thread handler ecc...
- cattura solo (sempre ad altissimo livello) "const std::exception &" e "..." (oltre alla base dell'eccezioni del framework che stai usando se non è derivata da std::exception.. ad esempio con MFC)
Ovviamente per far ciò DEVI applicare a man bassa tecniche RAII (Resource Acquisition Is Initialization).
Distingui gli errori logici da quelli runtime.
Nel mondo reale, in casi particolari necessiterai di catturare eccezioni a medio basso livello, altre volte ti sarà più comodo gestire l'errore con un if.
Leggiti un po' di informazioni sulle tecniche "Design by Contract".
EDIT: NON lanciare eccezioni nei distruttori (il che significa che le devi catturare tutte anche lì), ma ok il discorso diventa un po' lunghetto
;-)
E' solo un mio parere, ma secondo me le eccezioni rappresentano un modo inutile per gestire le eccezioni.
Posso trovare qualche minima utilità solo nella creazione di librerie esterne da distribuire.
In altri casi, a che serve lanciare un'eccezione che poi io stesso intercetterò? (Della serie "Uso le librerie che io stesso scrivo e quindi ho il codice sorgente sotto mano)
Ci sono le funzioni get/set per evitare che un parametro sia errato.
"Se proprio devono piratare, almeno piratino il nostro." (Bill Gates)
"Non è possibile che 2 istituzioni statali mi mettano esami nello stesso giorno." (XWolverineX)
http://xvincentx.netsons.org/programBlog
Certo se tu preferisci usare codice del tipo (è pseudo codice non testato):Originariamente inviato da XWolverineX
E' solo un mio parere, ma secondo me le eccezioni rappresentano un modo inutile per gestire le eccezioni.
Posso trovare qualche minima utilità solo nella creazione di librerie esterne da distribuire.
In altri casi, a che serve lanciare un'eccezione che poi io stesso intercetterò? (Della serie "Uso le librerie che io stesso scrivo e quindi ho il codice sorgente sotto mano)
Ci sono le funzioni get/set per evitare che un parametro sia errato.
rispetto a (è pseudo codice non testato)Codice PHP:
int MyHandleResource (){
int err = 0;
const char * kResId = "myResId";
Resource * aResource = NewResource ();
if (aResource){
if (LockResource (aResource, kResId)){
if (LoadResource (aResource, kResId)){
if (HandleResource (aResource)){
}
else{
err = 1;
HandleError ("HandleResource () error");
}
if (!UnloadResource (aResource)){
err = 2;
HandleError ("UnloadResourrce () error");
}
}
if (!UnlockResource (aResource, kResId)){
err = 3;
HandleError ("UnlockResource () error");
}
}
else{
err = 4;
HandleError ("LockResource () error");
}
if (!FreeResource (aResource)){
err = 5;
HandleError ("FreeResource () error");
}
aResource = NULL;
}
else{
err = 6;
HandleError ("NewResource () error");
}
return err;
}
buon per teCodice PHP:
void MyHandleResource (){
const char * kResId = "myResId";
Resource * aResource = NewResource ();
TempResource aTempResource (aResource);
TempLockResource aTempLockResource (aResource, kResId);
TempLoadResource aTempLoadResource (aResource);
RuntimeAssert (HandleResource (aResource));
}
;-)
Accidenti. Mi è venuto il mal di mare a vedere quello spaghetti code.![]()
secondo voi è giusto utilizzare entrambi i costrutti? Nel senso che a volte utilizzo l'if e a volte il try thow catch?
Sinceramente per una riga di codice a volte mi sembra sconsigliato utilizzare i try.
Attendo risposta
il punto è: usare innumerevoli if contro un solo try.. scegli tu.Originariamente inviato da Jar
secondo voi è giusto utilizzare entrambi i costrutti? Nel senso che a volte utilizzo l'if e a volte il try thow catch?
Sinceramente per una riga di codice a volte mi sembra sconsigliato utilizzare i try.
Attendo risposta
;-)
Generalmente il flusso di controllo delle strutture tradizionali è piu' chiaro e piu' efficiente.
Inoltre try...catch è utile usarlo solo per errori che devono essere gestiti fuori dallo scope in cui possono verificarsi.
Riprendendo il caso del "Faccio librerie che uso io stesso", avendo il codice sorgente in mano, è possibile rendere ogni gestione di errori interna al luogo in cui possono verificarsi.
Ribadisco quindi, che hanno utilità solo in librerie da distribuire compilate
"Se proprio devono piratare, almeno piratino il nostro." (Bill Gates)
"Non è possibile che 2 istituzioni statali mi mettano esami nello stesso giorno." (XWolverineX)
http://xvincentx.netsons.org/programBlog
Mi trovi completamente in disaccordo. Come ti è già stato fatto vedere l'uso delle eccezioni rende il codice molto più leggibile e comprensibile, senza contare che rende molto più comode da usare molte funzioni. Usando un approccio in stile Windows API agli errori devi usare sempre il valore di ritorno per il codice di errore (o riservare alla segnalazione di un errore un valore speciale), e il vero valore restituito andrà memorizzato in un parametro passato per riferimento o per indirizzo, rendendo la funzione molto più scomoda da usare. Non solo: le eccezioni risalgono lo stack fino a trovare un gestore adeguato, così non c'è bisogno che delle funzioni "intermedie" si preoccupino di controllare se si sono verificati errori che comunque non saprebbero come gestire: l'eccezione risale in automatico fino alla prima funzione in grado di gestirla, che spesso è l'unica che sa cosa fare se si verifica un problema.
Inoltre le eccezioni non si ignorano così facilmente come i valori restituiti (o quanto meno, per ignorarle bisogna mettere deliberatamente un blocco catchall), così è più difficile che passino inosservate.
Sicuramente non è più chiaro (dai un'occhiata allo spaghetti-code postato da MacApp), e se è più efficiente conta molto poco, visto che un'eccezione è, appunto, una situazione eccezionale, per cui anche se non è efficientissima è difficile che abbia un impatto percepibile sulle prestazioni del programma.Generalmente il flusso di controllo delle strutture tradizionali è piu' chiaro e piu' efficiente.
Sì, ma usando questo sistema è facile ottenere del codice illeggibile, senza contare che il passaggio della gestione dell'errore alla routine chiamante è sempre un pasticcio (come già detto poco sopra).Riprendendo il caso del "Faccio librerie che uso io stesso", avendo il codice sorgente in mano, è possibile rendere ogni gestione di errori interna al luogo in cui possono verificarsi.
Amaro C++, il gusto pieno dell'undefined behavior.