Odpowiedzi:
std::exception
to klasa, której jedynym celem jest służenie jako klasa bazowa w hierarchii wyjątków. Nie ma innych zastosowań. Innymi słowy, koncepcyjnie jest to klasa abstrakcyjna (mimo że nie jest definiowana jako klasa abstrakcyjna w znaczeniu tego terminu w języku C ++).
std::runtime_error
Jest to bardziej wyspecjalizowane klasy, z malejącym std::exception
, ma być wrzucony w przypadku różnych uruchomieniowych błędów. Ma podwójny cel. To może być rzucony przez siebie, lub może służyć jako klasy bazowej do różnych, nawet bardziej wyspecjalizowanych typów wyjątków Runtime error, takich jak std::range_error
, std::overflow_error
itd. Można definiować własne klasy wyjątków malejąco z std::runtime_error
, jak można zdefiniować własny wyjątek klasy wywodzące się od std::exception
.
Podobnie jak std::runtime_error
standardowa biblioteka zawiera std::logic_error
, również zstępującą z std::exception
.
Celem takiej hierarchii jest zapewnienie użytkownikowi możliwości wykorzystania pełnej mocy mechanizmu obsługi wyjątków C ++. Ponieważ klauzula „catch” może wychwytywać wyjątki polimorficzne, użytkownik może napisać klauzule „catch”, które mogą przechwytywać typy wyjątków z określonego poddrzewa hierarchii wyjątków. Na przykład, catch (std::runtime_error& e)
przechwyci wszystkie wyjątki z std::runtime_error
poddrzewa, pozwalając wszystkim innym przejść (i przelecieć dalej w górę stosu wywołań).
PS Projektowanie użytecznej hierarchii klas wyjątków (która pozwoliłaby na wychwycenie tylko tych typów wyjątków, którymi jesteś zainteresowany w każdym punkcie twojego kodu) jest nietrywialnym zadaniem. To, co widzisz w standardowej bibliotece C ++, jest jednym z możliwych rozwiązań, które oferują Ci autorzy języka. Jak widać, zdecydowali się podzielić wszystkie typy wyjątków na „błędy czasu wykonywania” i „błędy logiczne”, a następnie zezwolić na tworzenie własnych typów wyjątków. Istnieją oczywiście alternatywne sposoby uporządkowania tej hierarchii, które mogą być bardziej odpowiednie w Twoim projekcie.
Aktualizacja: przenośność Linux vs Windows
Jak zauważyli Loki Astari i unixman83 w swojej odpowiedzi i komentarzach poniżej, konstruktor exception
klasy nie przyjmuje żadnych argumentów zgodnie ze standardem C ++. Microsoft C ++ ma konstruktor pobierający argumenty w exception
klasie, ale nie jest to standard. runtime_error
Klasa ma maksymalnie wykorzystać konstruktor argumentów ( char*
) na obu platformach, Windows i Linux. Aby być przenośnym, lepiej używać runtime_error
.
(I pamiętaj, tylko dlatego, że specyfikacja twojego projektu mówi, że twój kod nie musi działać w systemie Linux, nie oznacza to, że nigdy nie musi działać w systemie Linux).
std::exception
. Jasne, wszystkie std
rzeczy rzucają klasy pochodne, ale nie ma absolutnie żadnego powodu, aby rzucać tylko std::exception
obiekty pochodne.
std::exception
należy wziąć pod uwagę (zwróć uwagę na rozważaną) abstrakcyjną podstawę standardowej hierarchii wyjątków. Dzieje się tak, ponieważ nie ma mechanizmu przekazywania określonej wiadomości (aby to zrobić, musisz wyprowadzić i wyspecjalizować what()
). Nic nie stoi na przeszkodzie, abyś używał std :: wyjątek, aw przypadku prostych aplikacji może to być wszystko, czego potrzebujesz.
std::runtime_error
z drugiej strony ma prawidłowe konstruktory, które akceptują ciąg znaków jako wiadomość. Gdy what()
jest wywoływana, zwracany jest wskaźnik const char, który wskazuje na łańcuch w języku C, który ma taki sam ciąg, jaki został przekazany do konstruktora.
try
{
if (badThingHappened)
{
throw std::runtime_error("Something Bad happened here");
}
}
catch(std::exception const& e)
{
std::cout << "Exception: " << e.what() << "\n";
}
std::exception(std::string)
. Teraz zdaję sobie sprawę, że muszę wrzucić, std::runtime_error
jeśli chcę, aby mój kod działał w systemie Linux (GCC).