- 1. Invariante
- 2. Arten von Ausnahmen
- 3. std::logic_error
- 4. std::invalid_argument
- 5. std::domain_error
- 6. std::length_error
- 7. std::out_of_range
- 8. std::future_error
- 9. std::runtime_error
- 10. std::range_error
- 11. std::overflow_error
- 12. std::underflow_error
- 13. std::system_error
- 14. std::ios_base::failure
- 15. std::bad_typeid
- 16. std::bad_cast
- 17. std::bad_weak_ptr
- 18. std::bad_function_call
- 19. std::bad_alloc
- 20. std::bad_array_new_length
- 21. std::bad_exception
Was ist eine Ausnahme? Dies ist eine Situation, die durch das Standardverhalten des Programms nicht vorgesehen ist. Versuchen Sie beispielsweise, auf ein Element in der Vector-Klasse zuzugreifen (das wir im Artikel classes besprochen haben), das nicht existiert. Das heißt, der Vektor ist außerhalb der Grenzen. In diesem Fall können Sie Ausnahmen verwenden, um die Programmausführung zu unterbrechen. Dies ist notwendig, weil
- In solchen Fällen weiß der Autor der Vector -Klasse in der Regel nicht, wie der Benutzer seine Klasse verwenden möchte, und weiß auch nicht, in welchem Programm diese Klasse verwendet wird.
- Der Benutzer der Vector -Klasse kann nicht immer den korrekten Betrieb dieser Klasse kontrollieren, also muss er informiert werden, dass etwas schief gelaufen ist.
Um solche Situationen in C++ zu lösen, können Sie die Technik der Ausnahmen verwenden.
Betrachten wir, wie eine Ausnahme geschrieben wird, wenn versucht wird, auf ein Element über einen Index zuzugreifen, der in der Vector-Klasse nicht vorhanden ist.
double& Vector::operator[](int i) { if (i<0 || size()<=i) throw out_of_range{"Vector::operator[]"}; return elem[i]; }
Hier gilt die Ausnahme
out_of_range.
Diese Ausnahme ist in der Header-Datei definiert
Der Operator throw übergibt die Steuerung an einen Ausnahmehandler vom Typ out_of_range in einer Funktion, die direkt oder indirekt Vector::operator aufruft. Um Ausnahmen zu behandeln, müssen Sie den Anweisungsblock try catch. verwenden.
void f(Vector& v) { // ... try { // блок обработки функции с исключением v[v.size()] = 7; // попытка доступа к элементу за пределами вектора } catch (out_of_range) { // ловим ошибку out_of_range // ... обработки ошибки out_of_range ... } // ... }
Invariante
Außerdem ermöglichen Ihnen try catch -Blöcke, mehrere verschiedene Ausnahmen zu behandeln, wodurch Invarianz in den Betrieb des C++-Ausnahmemechanismus eingeführt wird.
Beispielsweise kann die Vektorklasse, wenn sie erstellt wird, die falsche Größe des Vektors erhalten oder keinen freien Speicher für die Elemente finden, die sie enthalten wird.
Vector::Vector(int s) { if (s < 0) throw length_error{}; elem = new double[s]; sz = s; }
Dieser Konstruktor kann in zwei Fällen eine Ausnahme auslösen:
- Wenn als Größe -Argument ein negativer Wert übergeben wird
- Wenn der Operator new keinen Speicher zuweist
length_error ist der Standardoperator für Ausnahmen, da die std-Bibliothek diese Ausnahmen häufig in ihrer Arbeit verwendet.
Die Ausnahmebehandlung sieht folgendermaßen aus:
void test() { try { Vector v(−27); } catch (std::length_error) { // обработка отрицательного размера вектора } catch (std::bad_alloc) { // обработка ошибки выделения памяти } }
Sie können auch Ihre eigenen Ausnahmen hervorheben.
Arten von Ausnahmen
Alle Ausnahmen der Standardbibliothek erben von std::exception.
Derzeit gibt es folgende Arten von Ausnahmen:
- Logikfehler
- ungültiges_argument
- Domänenfehler
- Längenfehler
- außer Reichweite
- future_error (C++11)
- Laufzeit Fehler
- range_error
- overflow_error
- Unterlauffehler
- system_error (C++11)
- ios_base::failure (seit C++11)
- bad_typeid
- bad_cast
- bad_weak_ptr (C++11)
- bad_function_call (C++11)
- bad_alloc
- bad_array_new_length (C++11)
- schlechte_Ausnahme
- ios_base::failure (vor C++11)
std::logic_error
Ausnahme in Header-Datei definiert
Gibt den Objekttyp an, der als Ausnahme ausgelöst werden soll. Es meldet Fehler, die das Ergebnis einer falschen Logik innerhalb des Programms sind, wie z. B. eine Verletzung einer logischen Prämisse oder einer Klasse von Invarianten, die verhindert werden kann.
Diese Klasse dient als Grundlage für Fehler, die erst zur Laufzeit erkannt werden können.
std::invalid_argument
Ausnahme in Header-Datei definiert
Geerbt von std::logic_error. Definiert eine Ausnahme, die im Falle eines ungültigen Arguments ausgelöst wird.
Beispielsweise gibt MSDN ein Beispiel für ein Objekt der Bitset-Klasse aus der Standardbibliothek
// invalid_arg.cpp // compile with: /EHsc /GR #include <bitset> #include <iostream> using namespace std; int main( ) { try { bitset< 32 > bitset( string( "11001010101100001b100101010110000") ); } catch ( exception &e ) { cerr << "Caught " << e.what( ) << endl; cerr << "Type " << typeid( e ).name( ) << endl; }; } \* Output: Caught invalid bitset<N> char Type class std::invalid_argument *\
In diesem Beispiel wird eine ungültige Zeichenfolge übergeben, in der sich ein fehlerhaftes Zeichen „b“ befindet.
std::domain_error
Ausnahme in Header-Datei definiert
Geerbt von std::logic_error. Gibt eine Ausnahme an, die ausgelöst wird, wenn eine mathematische Funktion für das angegebene Argument nicht definiert ist, zum Beispiel:
std::sqrt(-1)
std::length_error
Ausnahme in Header-Datei definiert
Geerbt von std::logic_error. Gibt die Ausnahme an, die ausgelöst werden soll, wenn versucht wird, ein Out-of-Bounds für ein Objekt zu implementieren. Wie für die Größe des Vektors am Anfang des Artikels gezeigt.
std::out_of_range
Ausnahme in Header-Datei definiert
Geerbt von std::logic_error. Gibt die Ausnahme an, die ausgelöst werden soll, wenn der Wertebereich eines Objekts außerhalb der Grenzen liegt. Wie es für den Wertebereich des Vektors am Anfang des Artikels gezeigt wurde.
std::future_error
Ausnahme in Header-Datei definiert
Geerbt von std::logic_error. Diese Ausnahme kann ausgelöst werden, wenn eine Funktion, die im asynchronen Modus arbeitet und von der Threadbibliothek abhängt, nicht ausgeführt werden konnte. Diese Ausnahme trägt einen Fehlercode, der mit std::error_code kompatibel ist.
std::runtime_error
Ausnahme in Header-Datei definiert
Ist die Basisausnahme für Ausnahmen, die nicht einfach vorhergesagt werden können und zur Laufzeit ausgelöst werden müssen.
std::range_error
Ausnahme in Header-Datei definiert
Eine Ausnahme gilt für Fehler bei der Berechnung von Fließkommawerten, wenn der Computer den Wert nicht verarbeiten kann, weil er entweder zu groß oder zu klein ist. Wenn der Wert ein ganzzahliger Wert ist, müssen die Ausnahmen underflow_error oder overflow_error verwendet werden.
std::overflow_error
Ausnahme in Header-Datei definiert
Eine Ausnahme wird für Fehler bei der Berechnung von Gleitkommawerten vom ganzzahligen Typ verwendet, wenn die Zahl einen zu großen positiven Wert hat, positiv unendlich, bei dem es zu einem Genauigkeitsverlust kommt, d.h. das Ergebnis ist so groß, dass es nicht als IEEE754-Zahl dargestellt werden kann.
std::underflow_error
Ausnahme in Header-Datei definiert
Die Ausnahme wird für Fehler bei der Berechnung von Gleitkommawerten vom ganzzahligen Typ verwendet, bei denen es zu einem Genauigkeitsverlust kommt, d.h. das Ergebnis ist so klein, dass es nicht als IEEE754-Nummer dargestellt werden kann.
std::system_error
Ausnahme in Header-Datei definiert
std::system_error ist eine Art von Ausnahme, die von verschiedenen Standardbibliotheksfunktionen ausgelöst wird (normalerweise Funktionen, die mit dem Betriebssystem interagieren, wie z. B. der std::thread -Konstruktor), wobei die Ausnahme eine hat entsprechende * std::error_code * .
std::ios_base::failure
Ausnahme in Header-Datei definiert
Verantwortlich für Ausnahmen, die ausgelöst werden, wenn E/A-Funktionen fehlschlagen.
std::bad_typeid
Ausnahme in Header-Datei definiert
Eine Ausnahme dieses Typs wird ausgelöst, wenn der typeid -Operator auf einen Nullzeiger eines polymorphen Typs angewendet wird.
#include <iostream> #include <typeinfo> struct S { // Тип должен быть полиморфным virtual void f(); }; int main() { S* p = nullptr; try { std::cout << typeid(*p).name() << '\n'; } catch(const std::bad_typeid& e) { std::cout << e.what() << '\n'; } }
std::bad_cast
Ausnahme in Header-Datei definiert
Diese Ausnahme tritt auf, wenn versucht wird, ein Objekt in einen Objekttyp umzuwandeln, der keine Vererbungsbeziehung zu ihm hat.
#include <iostream> #include <typeinfo> struct Foo { virtual ~Foo() {} }; struct Bar { virtual ~Bar() {} }; int main() { Bar b; try { Foo& f = dynamic_cast<Foo&>(b); } catch(const std::bad_cast& e) { std::cout << e.what() << '\n'; } }
std::bad_weak_ptr
Ausnahme in Header-Datei definiert
std::bad_weak_ptr ist der Objekttyp, der als Ausnahme von std::shared_ptr -Konstruktoren ausgelöst wird, die std::weak_ptr als Argument nehmen, wenn std::weak_ptr darauf verweist ein bereits gelöschtes Objekt.
#include <memory> #include <iostream> int main() { std::shared_ptr<int> p1(new int(42)); std::weak_ptr<int> wp(p1); p1.reset(); try { std::shared_ptr<int> p2(wp); } catch(const std::bad_weak_ptr& e) { std::cout << e.what() << '\n'; } }
std::bad_function_call
Ausnahme in Header-Datei definiert
Diese Ausnahme wird ausgelöst, wenn die std::function::operator() -Methode des std::function -Objekts aufgerufen wurde und kein Funktionsobjekt erhalten hat, d. h. es wurde nullptr als an übergeben initializer, und das Funktionsobjekt wurde nie übergeben.
#include <iostream> #include <functional> int main() { std::function<int()> f = nullptr; try { f(); } catch(const std::bad_function_call& e) { std::cout << e.what() << '\n'; } }
std::bad_alloc
Ausnahme in Header-Datei definiert
Wird aufgerufen, wenn kein Arbeitsspeicher zugewiesen werden kann.
std::bad_array_new_length
Ausnahme in Header-Datei definiert
In den folgenden Fällen wird eine Ausnahme ausgelöst:
- Das Array hat eine negative Größe
- Die Gesamtgröße des neuen Arrays hat den von der Implementierung definierten Maximalwert überschritten
- Die Anzahl der Initialisierungselemente überschreitet die vorgeschlagene Anzahl der Initialisierungselemente
#include <iostream> #include <new> #include <climits> int main() { int negative = -1; int small = 1; int large = INT_MAX; try { new int[negative]; // negative size new int[small]{1,2,3}; // too many initializers new int[large][1000000]; // too large } catch(const std::bad_array_new_length &e) { std::cout << e.what() << '\n'; } }
std::bad_exception
Ausnahme in Header-Datei definiert
std::bad_exception ist eine Art C++-Ausnahme, die in den folgenden Situationen ausgelöst wird:
- Wenn die dynamische Ausnahmespezifikation verletzt wird
- Wenn std::exception_ptr eine Kopie der abgefangenen Ausnahme enthält und wenn der Kopierkonstruktor des Ausnahmeobjekts die aktuelle_Ausnahme abgefangen hat, dann wird eine abgefangene Ausnahme ausgelöst.
#include <iostream> #include <exception> #include <stdexcept> void my_unexp() { throw; } void test() throw(std::bad_exception) { throw std::runtime_error("test"); } int main() { std::set_unexpected(my_unexp); try { test(); } catch(const std::bad_exception& e) { std::cerr << "Caught " << e.what() << '\n'; } }
std::underflow_error - это не "число имеет слишком большое отрицательное значение", а потеря точности при вычислениях, т.е. результат настолько мал, что не может быть представлен числом в формате IEEE754
Спасибо. Дополнил.