Antworten:
std::exception
ist die Klasse, deren einziger Zweck darin besteht, als Basisklasse in der Ausnahmehierarchie zu dienen. Es hat keine anderen Verwendungen. Mit anderen Worten, konzeptionell ist es eine abstrakte Klasse (obwohl sie in der C ++ - Bedeutung des Begriffs nicht als abstrakte Klasse definiert ist).
std::runtime_error
ist eine speziellere Klasse, die von std::exception
verschiedenen Klassen abstammt und bei verschiedenen Laufzeitfehlern ausgelöst werden soll. Es hat einen doppelten Zweck. Es kann selbst geworfen werden, oder es kann auf verschiedene noch mehr spezialisierte Arten von Laufzeitfehlern Ausnahmen, wie zB als Basisklasse dienen std::range_error
, std::overflow_error
usw. Sie können Ihre eigenen Ausnahmeklassen absteigend von definieren std::runtime_error
, sowie Sie können Ihre eigene Ausnahme definieren Klassen absteigend von std::exception
.
Genau wie die std::runtime_error
Standardbibliothek enthält std::logic_error
, auch absteigend von std::exception
.
Der Sinn dieser Hierarchie besteht darin, dem Benutzer die Möglichkeit zu geben, die volle Leistungsfähigkeit des C ++ - Ausnahmebehandlungsmechanismus zu nutzen. Da die 'catch'-Klausel polymorphe Ausnahmen abfangen kann, kann der Benutzer' catch'-Klauseln schreiben, die Ausnahmetypen aus einem bestimmten Teilbaum der Ausnahmehierarchie abfangen können. Fängt beispielsweise catch (std::runtime_error& e)
alle Ausnahmen vom std::runtime_error
Teilbaum ab und lässt alle anderen durch (und fliegt weiter den Aufrufstapel hinauf).
PS Das Entwerfen einer nützlichen Ausnahmeklassenhierarchie (mit der Sie nur die Ausnahmetypen abfangen können, an denen Sie an jedem Punkt Ihres Codes interessiert sind) ist keine triviale Aufgabe. Was Sie in der Standard-C ++ - Bibliothek sehen, ist ein möglicher Ansatz, den Ihnen die Autoren der Sprache anbieten. Wie Sie sehen, haben sie beschlossen, alle Ausnahmetypen in "Laufzeitfehler" und "Logikfehler" aufzuteilen und von dort aus mit Ihren eigenen Ausnahmetypen fortzufahren. Es gibt natürlich alternative Möglichkeiten, diese Hierarchie zu strukturieren, die für Ihr Design möglicherweise besser geeignet sind.
Update: Portabilität Linux vs Windows
Wie Loki Astari und unixman83 in ihrer Antwort und ihren Kommentaren unten angegeben haben, akzeptiert der Konstruktor der exception
Klasse keine Argumente gemäß dem C ++ - Standard. Microsoft C ++ verfügt über einen Konstruktor, der Argumente in der exception
Klasse akzeptiert, dies ist jedoch kein Standard. Die runtime_error
Klasse verfügt über einen Konstruktor, der char*
auf beiden Plattformen, Windows und Linux , Argumente ( ) verwendet. Um tragbar zu sein, besser nutzen runtime_error
.
(Und denken Sie daran: Nur weil eine Spezifikation Ihres Projekts besagt, dass Ihr Code nicht unter Linux ausgeführt werden muss, bedeutet dies nicht, dass er niemals unter Linux ausgeführt werden muss.)
std::exception
. Sicher, alle std
Dinge werfen abgeleitete Klassen davon, aber es gibt absolut keinen Grund, nur std::exception
abgeleitete Objekte zu werfen .
std::exception
sollte als abstrakte Basis der Standardausnahmehierarchie betrachtet werden (beachten Sie die berücksichtigte). Dies liegt daran, dass es keinen Mechanismus gibt, um eine bestimmte Nachricht weiterzuleiten (dazu müssen Sie ableiten und spezialisieren what()
). Nichts hindert Sie daran, std :: exception zu verwenden, und für einfache Anwendungen ist dies möglicherweise alles, was Sie benötigen.
std::runtime_error
Auf der anderen Seite gibt es gültige Konstruktoren, die eine Zeichenfolge als Nachricht akzeptieren. Wenn what()
aufgerufen wird, wird ein const char-Zeiger zurückgegeben, der auf eine C-Zeichenfolge zeigt, die dieselbe Zeichenfolge hat, die an den Konstruktor übergeben wurde.
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)
. Jetzt ist mir klar, dass ich werfen muss, std::runtime_error
wenn mein Code unter Linux (GCC) funktionieren soll.