PDA

Visualizza la versione completa : Linguaggio C++... cosa mi conviene fare?


Jar
06-05-2008, 19:55
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

shodan
06-05-2008, 20:28
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.

MacApp
06-05-2008, 21:18
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
;-)

XWolverineX
06-05-2008, 21:59
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.

MacApp
06-05-2008, 22:19
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.

Certo se tu preferisci usare codice del tipo (è pseudo codice non testato):


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;
}


rispetto a (è pseudo codice non testato)


void MyHandleResource (){
const char * kResId = "myResId";
Resource * aResource = NewResource ();
TempResource aTempResource (aResource);
TempLockResource aTempLockResource (aResource, kResId);
TempLoadResource aTempLoadResource (aResource);
RuntimeAssert (HandleResource (aResource));
}


buon per te
;-)

shodan
06-05-2008, 22:34
Accidenti. Mi è venuto il mal di mare a vedere quello spaghetti code. :dottò:

Jar
06-05-2008, 22:56
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

MacApp
07-05-2008, 07:20
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
il punto è: usare innumerevoli if contro un solo try.. scegli tu.
;-)

XWolverineX
07-05-2008, 14:56
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

MItaly
07-05-2008, 15:48
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.

Generalmente il flusso di controllo delle strutture tradizionali è piu' chiaro e piu' efficiente.
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.

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.

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).

Loading