2011-07-23 13 views
25

Czy należy używać throw new FoobarException(Baz argument); lub throw FoobarException(Baz argument);?C++: Zgłaszanie wyjątków, użyj "nowego" czy nie?

Podczas łapania zawsze używam catch(FoobarException& e) "na wszelki wypadek", ale nigdy nie mogłem znaleźć solidnej odpowiedzi, czy musiałbym użyć nowego, czy nie w C++ (Java zdecydowanie) lub czy było to po prostu preferencją programisty.

+2

Nie sądzę, że się złapie, jeśli rzucisz za pomocą wskaźnika i spróbujesz złapać przez referencję, prawda? –

+2

Jeśli użyjesz nowego, to 'catch (FoobarException &)' nie będzie przechwytywać twojego obiektu. nowy tworzy wskaźniki. –

Odpowiedz

33

Wyjątki w C++ powinny być rzucane przez wartość i przechwytywane przez odniesienie.

Więc to jest właściwy sposób:

try 
{ 
    throw FoobarException(argument); 
} 
catch(const FoobarException &ex) 
{ 
    cout << ex.what() << endl; 
} 

Nie wyjątek utworzony z nowym, ponieważ kto jest odpowiedzialny za usuwanie nie jest dobrze zdefiniowana. Ponadto wykonywanie alokacji podczas obsługi błędów może spowodować inny wyjątek, przesłaniając pierwotny problem.

Nie musisz przechwytywać przez odwołanie do wartości stałej (nie działa const, ale działa to dobrze). Powinieneś jednak zawsze przez odniesienie (nie wartości), aby wychwycić wyjątek polimorficznie. Jeśli tego nie zrobisz, typ wyjątku może zostać skrócony.

+0

Dlaczego wyjątek powinien zawsze być przechwytywany przez odniesienie nie według wartości? Czy mówisz o problemie z dzieleniem obiektów ze względu na przekazywanie obiektu pochodnego przez wartość do metody, która oczekuje argumentu obiektu klasy bazowej? – Destructor

7

chyba że jest jakiś szczególny wymóg, aby tego nie robić, zawsze rzucam według wartości i przechwytu przez odniesienie const. Wynika to z faktu, że sama usługa new może również zgłaszać wyjątki podczas obsługi błędów, najlepiej unikać sytuacji, które mogą powodować wyjątki.

+0

Zgadza się, rzucając wyjątek podczas gdy inny wyjątek jest aktywny jest zasadniczo zabroniony (myślę, że to UB), więc standardowe 'nowe' jest obecnie niedostępne. Mógłbyś użyć jakiegoś przydziału, który nie musiałbyś rzucać, gdybyś naprawdę musiał, ale to wciąż szalone :-) –

+1

Moje 2c's: Wystarczy dodać do mędrca rady @KerrekSB, to jest rzeczywiście zdefiniowane zachowanie (zobacz http: //en.cppreference .com/w/cpp/error/terminate). Powyższy link wskazuje również na wiele innych rzeczy, których najlepiej unikać (takich jak rzucanie wyjątków od destruktorów, ponieważ wtedy możesz skończyć z podnoszeniem wyjątków, podczas gdy stos jest rozwijany dla wcześniej wyrzuconego wyjątku). – Rob

Powiązane problemy