2012-10-22 5 views
5

Mam zestaw funkcji i muszę przekonwertować potencjalnie zgłaszane wyjątki na kody błędów .Czy makro jest w stanie złapać zestaw wyjątków w różnych miejscach w porządku?

W tym celu mam owinięty rzeczywiste połączenia ze sprawozdania 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; 
    } 
} 

... 

Te statmements połowowe powtarzają się. Dodatkowo, gdy dodawany jest nowy wyjątek , do każdego opakowania wywołania musi zostać dodana nowa klauzula catch.

Czy poniższe makro zastępuje instrukcje catch?

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

Które skutkuje:

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

    return E_SUCCESS; 
    } 
    CATCH_ALL_EXCEPTIONS 
+0

dlaczego nie mogę być odpowiednie? zależy to od tego, jak chcesz poprawnie napisać swój kod? –

+1

@markus_p, zależy to również od tego, jak inne czyta kod w późniejszym czasie (tj. Łatwość konserwacji). – iammilind

+0

@iammilind prawda, ale g_with_error_codes faktycznie zabija wszystkie te (widoczność) już. w tym przypadku makro jest widoczne tylko dla faceta, który przekopuje się do źródła. –

Odpowiedz

9

Można użyć funkcji zamiast makra tak:

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

Twoim przypadku, nie trzeba żadnych makro.
Wystarczy prosta klasa podstawowa zawierająca virtual funkcja.

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 
} 

Teraz dziedziczyć tej klasy ze wszystkimi error# klas:

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

Wreszcie kod jest tak łatwe, jak to:

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

Nie przejmuj się o koszty virtual działa tutaj. Ponieważ jest minimalny, a wyjątki są rzadkimi zdarzeniami; bardzo mały koszt virtual ness jest warta, aby twój kod był łatwy w utrzymaniu i rozszerzalny.

+1

Dziękuję za poświęcenie czasu. Wolałbym nie zmieniać struktury używanego wyjątku, ale uważam, że twoja odpowiedź ma wartość dla osób, które mogą zmienić swoje klasy wyjątków. –

Powiązane problemy