2009-10-15 18 views

Antwort

129

std::exception ist die Klasse, deren einziger Zweck darin besteht, als Basisklasse in der Ausnahmehierarchie zu dienen. Es hat keine anderen Anwendungen. Mit anderen Worten, konzeptionell ist es eine abstrakte Klasse (obwohl sie nicht als abstrakte Klasse in C++ definiert ist, was den Begriff bedeutet).

std::runtime_error ist eine speziellere Klasse von std::exception absteigend, bestimmt bei verschiedenen Laufzeit Fehler geworfen werden. Es hat einen doppelten Zweck. Es kann von selbst ausgelöst werden, oder es kann als Basisklasse für verschiedene, noch speziellere Arten von Laufzeitfehlerausnahmen dienen, wie std::range_error, std::overflow_error usw. Sie können eigene Ausnahmeklassen definieren, die von std::runtime_error abstammen, sowie Sie definieren können Ihre eigenen Ausnahmeklassen, die von std::exception abstammen.

Genau wie std::runtime_error enthält die Standardbibliothek std::logic_error, ebenfalls absteigend von std::exception.

Der Zweck 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 von einem bestimmten Teilbaum der Ausnahmehierarchie abfangen können. Zum Beispiel fängt catch (std::runtime_error& e) alle Ausnahmen von std::runtime_error Teilbaum, lassen Sie alle anderen passieren (und fliegen weiter nach oben auf den Call-Stack).

P.S. Das Entwickeln einer nützlichen Ausnahmeklassenhierarchie (mit der Sie nur die Ausnahmetypen abfangen können, an denen Sie an jedem Punkt Ihres Codes interessiert sind) ist eine nicht-triviale Aufgabe. Was Sie in der Standard-C++ - Bibliothek sehen, ist ein möglicher Ansatz, der Ihnen von den Autoren der Sprache angeboten wird. Wie Sie sehen, haben sie sich dafür entschieden, alle Ausnahmetypen in "Laufzeitfehler" und "Logikfehler" aufzuteilen und von dort aus mit eigenen Ausnahmetypen fortzufahren. Es gibt natürlich alternative Möglichkeiten, diese Hierarchie zu strukturieren, die für Ihr Design geeigneter sein könnte.

Update: Portabilität Linux vs Windows-

Als Loki Astari und unixman83 in ihrer Antwort zur Kenntnis genommen und Kommentaren unten, der Konstruktor der exception Klasse nimmt keine Argumente nach C++ Standard. Microsoft C++ hat einen Konstruktor, der Argumente in der Klasse exception nimmt, aber dies ist kein Standard. Die Klasse runtime_error hat einen Konstruktor, der auf beiden Plattformen, Windows und Linux, Argumente entgegennimmt (char*). Um tragbar zu sein, verwenden Sie besser runtime_error.

(Und denken Sie daran, nur weil eine Spezifikation des Projekts sagt Ihr Code nicht auf Linux laufen hat, bedeutet es nicht, es nie auf Linux laufen muss.)

+0

danke. gute Antwort. obwohl ich mich frage, ob es jemals eine andere art von ausnahme geben muss ... nur ein gedanke. – sivabudh

+0

Wenn es eine Toleranz gibt, von der die Ausnahme erneut abgedeckt werden kann, kann eine andere Art von Ausnahme nützlich sein, da wir den Ausnahmebehandlungsmechanismus verwenden können, um die Ausnahme an den Handler zu verweisen, der das Problem beheben wird. Wenn es keine Chance auf Wiederherstellung gibt, ist eine der Standardausnahmen in Ordnung. –

+1

Nur als Nebenbemerkung: Es gibt nirgendwo eine Regel, die Sie zwingt, von 'std :: exception' abzuleiten. Sicher, alle 'std' Dinge werfen davon abgeleitete Klassen ab, aber es gibt absolut keinen Grund, nur" std :: exception "abgeleitete Objekte zu werfen. – rubenvb

15

std :: Ausnahme sein sollte berücksichtigt (beachten Sie die Überlegung) die abstrakte Basis der Standardausnahmehierarchie. Dies liegt daran, dass es keinen Mechanismus gibt, um eine bestimmte Nachricht zu übergeben (dazu müssen Sie what()) ableiten und spezialisieren. Es gibt nichts, was Sie daran hindern könnte, std :: exception zu verwenden, und für einfache Anwendungen könnte es alles sein, was Sie brauchen.

std :: runtime_error auf der anderen Seite hat 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 die gleiche 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"; 
} 
+1

Danke für die Antwort Martin. Allerdings verwende ich std :: exception() auf die gleiche Weise wie oben beschrieben. h., std :: exception() -Konstruktor kann auch eine std :: string() oder const char * nehmen. – sivabudh

+12

Nicht gemäß der Norm. std :: exception hat einen Konstruktor, der keine Argumente annimmt. Das Verwenden einer Version, die eine Std :: Zeichenfolge oder eine C-Zeichenfolge akzeptiert, ist nicht portierbar. –

+7

Aufgrund von Microsoft habe ich mich daran gewöhnt, 'std :: exception (std :: string)' zu werfen. Jetzt erkenne ich, dass ich 'std :: runtime_error' werfen muss, wenn ich möchte, dass mein Code in Linux (GCC) funktioniert. – unixman83

Verwandte Themen