2012-04-21 10 views
5

Sto usando QT 4.8 (C++) per il progetto applicazione desktop, e la scrittura di gestione delle eccezioni, che è la seguente:Come evitare di scrivere codice ripetuto nei blocchi di cattura?

void callerMethod() 
{ 
    try 
    { 
    method1(); 
    } 
    catch(Exception1& e) 
    { 
    // display critcal error message 
    // abort application 
    } 
    catch(std::Exception& e) 
    { 
    // print exception error message 
    } 
    catch(...) 
    { 
    // print unknown exception message 
    } 
} 

void method1() 
{ 
    try 
    { 
    // some initializations 
    // some operations (here exceptions can occur) 
    // clean-up code (for successful operation i.e no exception occurred) 
    } 
    catch(Exception1& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(Exception2& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(Exception3& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(...) 
    { 
    // clean-up code 
    throw; 
    } 
} 

Quindi la mia domanda ho bisogno di scrivere il codice di clean-up in ogni blocco catch ? È possibile che io possa evitare di scrivere codice ripetuto?

NOTA :: [In method1()] Voglio ri-generare eccezioni che si sono verificati alla mia caller.So non posso prenderli in blocco catch singolo, perché quindi digitare le informazioni verranno perse .

+4

Prova t o ridurre la quantità di codice di pulizia necessaria utilizzando puntatori intelligenti, classi di contenitori, ecc. Idealmente non dovrebbe esserci alcun codice di pulizia. – user763305

+0

Sembra che ciò che si vuole fare è semplicemente 'provare {/ * può lanciare * /} catch (const_e_specifica_specifica specifica) {/ * termina * /}'. Se non ti interessa i tipi di eccezione 'Exception1',' Exception2' e così via, quindi * non * li cattura. –

+1

Inoltre, anche se si cattura per riferimento, si dovrebbe * ricominciare usando 'throw;' invece di 'throw e;' per evitare l'affettamento. – ereOn

risposta

8

Method1 può essere molto semplificata da due concetti:

  1. RAII. Inserisci qualsiasi codice di pulizia in distruttori e il codice di pulizia sarà centralizzato.
  2. Utilizzare il numero non valido throw e non è necessario conoscere il tipo di eccezione generata.

Quindi, method1() dovrebbe essere simile:

void method1() 
{ 
    // some initializations of RAII objects 
    // some operations (here exceptions can occur) 
} 

La prima catch clausola callerMethod può essere rimosso se si deriva da Exception1 std::exception, poiché il metodo what() è virtuale.

+1

+1. Volevo dirlo RAII è la soluzione qui. – Nawaz

+0

Ma voglio gestire Exception1 separatamente in callerMethod(). Se si è verificata l'eccezione1, desidero interrompere l'applicazione. – EngineeredBrain

+0

@AnwarShaikh: puoi ancora farlo. RAII risolve solo il tuo problema di pulizia. – Nawaz

0

Se tutto il codice vostra pulizia è del tutto identico, si può fare tutto nella vostra catch (...) Blocco:

try { 
    // code 
} catch (...) { 
    // cleanup 
    throw; 
} 

Se il codice varia leggermente, si può sempre chiamare una funzione di pulizia:

try { 
    // code 
} catch (exc1 ex) { 
    cleanup(args); 
    // exc1 specific 
    throw; 
} catch (exc2 ex) { 
    cleanup(args); 
    // exc2 specific 
    throw; 
} catch (...) { 
    cleanup(args); 
    throw; 
} 
+0

Se scrivo un solo fermo (..) che genera un'eccezione, nel metodo del chiamante Come saprò quale eccezione si è verificata. Perché voglio gestire Exception1 che interrompe l'applicazione. – EngineeredBrain

1

È consigliabile generare eccezioni il più basse possibile e catturarle il più in alto possibile nella catena di chiamate. Ciò porta automaticamente ad una minore duplicazione del codice e centralizza la gestione degli errori. Stai lanciando/catturando tutto in un posto, che sembra un po '... forzato.

faccio spesso questo genere di cose (soprattutto per le eccezioni di programma-chiusura.

int main() 
try 
{ 
    function_calls_that_may_throw(); 
    // ... 
} 
catch(my_exception& e) 
{ 
    e.do_exception_stuff(); 
} 
catch(std::exception& e) 
{ 
    std::cout << e.what(); 
} 
catch(...) 
{ 
    std::cout << "Something bad happened.\n"; 
} 

Questo è possibile solo per generare eccezioni non si ha intenzione di gestire meglio o ritentare l'operazione non riuscita o qualcosa

Il pro di questo approccio è che tutto/più codice di gestione degli errori è al livello più alto del tuo programma, e tutte le funzioni nella catena di chiamate non devono preoccuparsi un po 'di questa roba, tutto quello che fanno è lanciare un'eccezione quando ne hanno voglia.

Problemi correlati