Bardzo słabo rozumiem obsługę wyjątków (tj. Jak dostosować instrukcje rzucania, próbowania, łapania do własnych celów).
Na przykład zdefiniowałem funkcję w następujący sposób: int compare(int a, int b){...}
Chciałbym, aby funkcja generowała wyjątek z pewną wiadomością, gdy a lub b jest ujemne.
Jak mam podejść do tego w definicji funkcji?
c++
exception-handling
Terry Li
źródło
źródło
unsigned int
jako parametry w sygnaturze funkcji. Z drugiej strony jestem ze szkoły, że powinieneś rzucać i wychwytywać wyjątki tylko dla rzeczy, które są naprawdę wyjątkowe.throw()
specyfikacji wyjątków dotyczących funkcji.Odpowiedzi:
Prosty:
Biblioteka standardowa zawiera ładną kolekcję wbudowanych obiektów wyjątków, które można rzucać. Pamiętaj, że zawsze powinieneś rzucać według wartości i łapać przez referencję:
Po każdej próbie możesz mieć wiele instrukcji catch (), więc możesz oddzielnie obsługiwać różne typy wyjątków.
Możesz także ponownie rzucić wyjątki:
Aby wychwycić wyjątki niezależnie od typu:
źródło
throw;
(ponowne rzucanie oryginalnego obiektu i zachowanie jego typu) zamiastthrow e;
(rzucanie kopią złapanego obiektu, ewentualnie zmianę jego typu).Wystarczy dodać w
throw
razie potrzeby itry
zablokować osobę dzwoniącą, która obsługuje błąd. Zgodnie z konwencją powinieneś rzucać tylko rzeczy, które pochodząstd::exception
, więc dołącz<stdexcept>
najpierw.Zobacz także wyjątek Boost.Exception .
źródło
Chociaż to pytanie jest dość stare i już na nie udzielono odpowiedzi, chcę tylko dodać notatkę o tym, jak poprawnie obsługiwać wyjątki w C ++ 11:
Użyj
std::nested_exception
istd::throw_with_nested
Jest to opisane na StackOverflow tutaj i tutaj , w jaki sposób można uzyskać ślad na swoich wyjątków wewnątrz kodu bez konieczności uciążliwego debugger lub logowania, po prostu pisząc odpowiedni program obsługi wyjątków, które będą rethrow zagnieżdżone wyjątki.
Ponieważ możesz to zrobić z dowolną pochodną klasą wyjątku, możesz dodać wiele informacji do takiego śladu wstecznego! Możesz także spojrzeć na moje rzucić MWE na GitHub , gdzie ślad może wyglądać mniej więcej tak:
źródło
Możesz zdefiniować komunikat, który zostanie wyświetlony, gdy wystąpi określony błąd:
lub możesz to zdefiniować w ten sposób:
Zazwyczaj miałbyś taki
try ... catch
blok:źródło
Chciał DODAJ do innych odpowiedzi opisanych tutaj dodatkowa uwaga, w przypadku niestandardowych wyjątków .
W przypadku tworzenia własnego niestandardowego wyjątku, który wywodzi się z tego
std::exception
, kiedy wychwytujesz „wszystkie możliwe” typy wyjątków, zawsze powinieneś zaczynaćcatch
klauzule od „najbardziej pochodnych” typów wyjątków, które mogą zostać przechwycone. Zobacz przykład (czego NIE robić):UWAGA:
0) Właściwa kolejność powinna być na odwrót, tj. - najpierw ty,
catch (const MyException& e)
a następniecatch (const std::exception& e)
.1) Jak widać, po uruchomieniu programu w obecnej postaci zostanie wykonana pierwsza klauzula catch (prawdopodobnie tego właśnie NIE oczekiwałeś).
2) Mimo że typ wychwycony w pierwszej klauzuli catch jest typu
std::exception
,what()
zostanie wywołana „właściwa” wersja - ponieważ zostanie ona przechwycona przez odwołanie (zmień przynajmniejstd::exception
typ przechwyconego argumentu na wartość - i doświadczysz zjawiska „krojenia obiektów” w akcji).3) W przypadku, gdy „jakiś kod z powodu faktu, że został zgłoszony wyjątek XXX ...” robi ważne rzeczy W ODNIESIENIU do typu wyjątku, oznacza to nieprawidłowe zachowanie się kodu.
4) Ma to również znaczenie, jeśli złapane obiekty były obiektami „normalnymi”, takimi jak:
class Base{};
iclass Derived : public Base {}
…5)
g++ 7.3.0
w systemie Ubuntu 18.04.1 wyświetla ostrzeżenie wskazujące na wspomniany problem:Znowu powiem, że ta odpowiedź jest DODAJ tylko do innych opisanych tutaj odpowiedzi (myślałem, że ten punkt warto wspomnieć, ale nie mogę go przedstawić w komentarzu).
źródło