2010-02-18 3 views
9

Oto konfiguracja.Co się stanie, jeśli użyję "rzutu"; bez wyjątku do rzutu?

Mam C++ program, który wywołuje kilka funkcji, z których wszystkie potencjalnie rzucić ten sam zestaw wyjątku, a ja chcę to samo zachowanie dla wyjątków w każdej funkcji (np drukowania komunikat o błędzie & przywrócić wszystkie dane do domyślnego dla wyjątkuA; po prostu wydrukuj dla wyjątkuB; zamknij całkowicie dla wszystkich innych wyjątków).

Wydaje się, że powinienem być w stanie ustawić zachowanie catch zadzwonić prywatną funkcję, która po prostu ponownie generuje błąd i wykonuje połowy, tak jak poniżej:

void aFunction() 
{ 
    try{ /* do some stuff that might throw */ } 
    catch(...){handle();} 
} 

void bFunction() 
{ 
    try{ /* do some stuff that might throw */ } 
    catch(...){handle();} 
} 

void handle() 
{ 
    try{throw;} 
    catch(anException) 
    { 
     // common code for both aFunction and bFunction 
     // involving the exception they threw 
    } 
    catch(anotherException) 
    { 
     // common code for both aFunction and bFunction 
     // involving the exception they threw 
    } 
    catch(...) 
    { 
     // common code for both aFunction and bFunction 
     // involving the exception they threw 
    } 
} 

Teraz, co się stanie, jeśli „obsłużyć” jest wywoływany poza klasą wyjątków. Jestem świadomy, że to nigdy nie powinno się zdarzyć, ale zastanawiam się, czy zachowanie jest niezdefiniowane przez standard C++.

+0

Zostaje zakończony, ale co mam zrobić ?, zapewni kompilator do uruchomienia tego programu, aby można było zweryfikować wynik. –

+0

Wszystko, co zrobi kompilator, to go skompilować. I to się skompiluje, ponieważ nie ma nic na temat * definicji * uchwytu, aby ostrzec użytkownika, że ​​na pewno będzie wymagał załadowanego wyjątku. Kompilatory nie mogą ci powiedzieć wiele przydatne o niezdefiniowanym zachowaniu, zwłaszcza coś takiego, że nie zostanie pobrane do czasu wykonywania. – deworde

Odpowiedz

16

Jeśli zostanie wywołane handle() poza kontekstem wyjątku, będzie można uzyskać throw bez obsługi wyjątku. W tym przypadku średnia (patrz punkt 15.5.1) określa, że ​​

Jeśli żaden wyjątek jest obecnie obsługiwane, wykonując throw-expression z połączeń nie operand terminate().

, więc Twój wniosek zostanie rozwiązany. To chyba nie jest to, czego chcesz tutaj.

+0

Cóż, nie ma żadnego rozsądnego powodu, aby wywoływać "handle()", jeśli nie ma cię w bloku catch, ale interesowało mnie, czy to, co się zdarzy, zostanie zdefiniowane. To była doskonała odpowiedź. Dzięki! – deworde

5

Jeśli użyjesz throw wewnątrz bloku catch, to wyrzuci wyjątek. Jeśli użyjesz rzut poza blokiem catch, to zakończy aplikację.

+0

Dobra odpowiedź, chociaż John był bardziej przejrzysty. Dzięki! – deworde

1

Nigdy, nigdy, nigdy, nigdy nie używaj catch (...), ponieważ możesz złapać błędy aplikacji, których nie chcesz przechwytywać, np. błędy, naruszenia zasad dostępu (w zależności od sposobu kompilacji).

Przeczytaj wielką książkę Johna Robbinsa (Debugowanie aplikacji systemu Windows), w której wyjaśnia bardziej szczegółowo, dlaczego nie powinieneś tego robić.

+0

http://stackoverflow.com/questions/2183113/using-catch-ellipsis-for-post-mortem-analysis –

+2

Jest to całkowicie nieistotne dla mojego pytania. Ponadto, jest to niedokładne, jak pokazano powyżej. Istnieje wiele doskonale uzasadnionych powodów (...), o ile dobrze sobie z tym poradzisz. Załóżmy na przykład, że chcę zwolnić blokadę udostępnionego elementu. Mógłbym poczekać, aż dotrze do destruktora, ale lepiej to zrobić, jak tylko jestem pewien, że już go nie potrzebuję. Mogłem wtedy ponownie rzucić z wnętrza bloku catch (...) {}, gdybym chciał, aby naruszenia i błędy dostępu nadal prowadziły do ​​zakończenia. – deworde