2012-10-22 10 views
5

Ho un set di funzioni e ho bisogno di convertire le eccezioni potenzialmente lanciate nei codici di errore .Una macro è in grado di rilevare una serie di eccezioni in luoghi diversi?

A tal fine ho avvolto le chiamate reali con le dichiarazioni try/catch:

int f_with_error_codes() 
{ 
    try { 
    f(); // wrapped function call 

    return E_SUCCESS; 
    } 
    catch (error1&) { 
    return E_ERROR1; 
    } 
    catch (error2&) { 
    return E_ERROR2; 
    } 
} 

int g_with_error_codes(int a); 
{ 
    try { 
    G g(a);  // wrapped expressions 
    g.print(); 

    return E_SUCCESS; 
    } 
    catch (error1&) { 
    return E_ERROR1; 
    } 
    catch (error2&) { 
    return E_ERROR2; 
    } 
} 

... 

Questi statmements di cattura si ripetono. Inoltre, ogni volta che viene aggiunta una nuova eccezione , è necessario aggiungere una nuova clausola di catch a ogni call wrapper.

È una macro simile di seguito per la sostituzione delle istruzioni catch appropriate?

#define CATCH_ALL_EXCEPTIONS \ 
catch (error1&) {    \ 
    return E_ERROR1;   \ 
}        \ 
catch (error2&) {    \ 
    return E_ERROR2;   \ 
} 

Quali sarebbero i risultati in:

int f_with_error_codes() 
{ 
    try { 
    f(); // the wrapped 

    return E_SUCCESS; 
    } 
    CATCH_ALL_EXCEPTIONS 
+0

perché non dovrei essere appropriato? dipende da come vuoi scrivere il tuo codice giusto? –

+1

@markus_p, dipende anche da come altri legge il codice in un secondo momento (ovvero la manutenibilità). – iammilind

+0

@iammilind true, ma g_with_error_codes uccide effettivamente tutti questi (visibilità) già. in questo caso la macro è visibile solo per il ragazzo che scava nella fonte. –

risposta

9

È possibile utilizzare una funzione invece di una macro come questa:

int f_with_error_codes() 
{ 
    try { 
    f(); // wrapped function call 

    return E_SUCCESS; 
    } 
    catch (...) { 
    return error_code(); 
    } 
} 

int error_code() 
{ 
    try { 
    throw; 
    } 
    catch (error1&) { 
    return E_ERROR1; 
    } 
    catch (error2&) { 
    return E_ERROR2; 
    } 
} 
7

per il vostro caso, non hai bisogno di alcuna macro.
Solo una semplice classe base contenente la funzione virtual sarà sufficiente.

class error : public std::exception { // std::exception is your wish 
    const char* what() throw(); // needed if std::exception is based 
    virtual int GetValue() const = 0; // <--- This is the core part 
} 

Ora, ricevete in eredità questa classe con tutti i error# classi:

class error1 : public error { 
    virtual int GetValue() const { return E_ERROR1; } // <--- override 
}; 
// ... 

Infine il codice è facile come questo:

void f_with_error_codes() 
{ 
    try { 
    f(); // wrapped function call 
    return E_SUCCESS; 
    } 
    catch (error& e) { // <--- base handle 
    return e.GetValue(); 
    } 
} 

Non preoccupatevi circa il costo di virtual funzione qui. Perché è minimo e anche le eccezioni sono eventi rari; un costo molto piccolo di virtual ness vale la pena di rendere il codice manutenibile ed estensibile.

+1

Grazie per aver dedicato tempo. Preferirei non modificare la struttura delle eccezioni utilizzate, ma penso che la risposta sia di valore per le persone che possono modificare le loro classi di eccezioni. –

Problemi correlati