Ich habe ein sehr schlechtes Verständnis für die Ausnahmebehandlung (dh wie man Throw-, Try- und Catch-Anweisungen für meine eigenen Zwecke anpasst).
Zum Beispiel habe ich eine Funktion wie folgt definiert: int compare(int a, int b){...}
Ich möchte, dass die Funktion eine Ausnahme mit einer Meldung auslöst, wenn entweder a oder b negativ ist.
Wie soll ich das bei der Definition der Funktion angehen?
c++
exception-handling
Terry Li
quelle
quelle
unsigned int
die Parameter in Ihrer Funktionssignatur angeben. Andererseits bin ich von der Schule, dass Sie nur Ausnahmen für Dinge werfen und fangen sollten, die tatsächlich außergewöhnlich sind.throw()
Ausnahmespezifikationen für Funktionen verwenden sollte.Antworten:
Einfach:
Die Standardbibliothek enthält eine schöne Sammlung integrierter Ausnahmeobjekte, die Sie werfen können. Denken Sie daran, dass Sie immer nach Wert werfen und nach Referenz fangen sollten:
Sie können nach jedem Versuch mehrere catch () -Anweisungen verwenden, sodass Sie verschiedene Ausnahmetypen separat behandeln können, wenn Sie möchten.
Sie können Ausnahmen auch erneut auslösen:
Und um Ausnahmen unabhängig vom Typ zu fangen:
quelle
throw;
(erneutes Werfen des ursprünglichen Objekts und Beibehalten seines Typs) anstattthrow e;
(Werfen einer Kopie des gefangenen Objekts, möglicherweise Ändern seines Typs) erneut werfen.Fügen Sie einfach
throw
bei Bedarf hinzu undtry
blockieren Sie den Anrufer, der den Fehler behandelt. Konventionell sollten Sie nur Dinge werfen, die von abgeleitet sindstd::exception
, also<stdexcept>
zuerst einschließen .Schauen Sie sich auch Boost.Exception an .
quelle
Obwohl diese Frage ziemlich alt ist und bereits beantwortet wurde, möchte ich nur einen Hinweis zur ordnungsgemäßen Behandlung von Ausnahmen in C ++ 11 hinzufügen:
Verwenden Sie
std::nested_exception
undstd::throw_with_nested
In StackOverflow wird hier und hier beschrieben , wie Sie eine Rückverfolgung Ihrer Ausnahmen in Ihrem Code erhalten können, ohne dass ein Debugger oder eine umständliche Protokollierung erforderlich ist, indem Sie einfach einen geeigneten Ausnahmebehandler schreiben, der verschachtelte Ausnahmen erneut auslöst.
Da Sie dies mit jeder abgeleiteten Ausnahmeklasse tun können, können Sie einer solchen Rückverfolgung viele Informationen hinzufügen! Sie können sich auch mein MWE auf GitHub ansehen, wo ein Backtrace ungefähr so aussehen würde:
quelle
Sie können eine Nachricht definieren, die ausgelöst werden soll, wenn ein bestimmter Fehler auftritt:
oder Sie könnten es so definieren:
Normalerweise haben Sie einen
try ... catch
Block wie diesen:quelle
Wollte ADD zu den anderen Antworten hier eine zusätzliche Note beschrieben, im Fall von benutzerdefinierten Ausnahmen .
std::exception
Wenn Sie eine eigene benutzerdefinierte Ausnahme erstellen, die sich aus dem Abfangen "aller möglichen" Ausnahmetypen ergibt , sollten Sie diecatch
Klauseln immer mit dem "am meisten abgeleiteten" Ausnahmetyp beginnen, der möglicherweise abgefangen wird. Siehe das Beispiel (was NICHT zu tun ist):HINWEIS:
0) Die richtige Reihenfolge sollte umgekehrt sein, dh zuerst Sie
catch (const MyException& e)
, gefolgt voncatch (const std::exception& e)
.1) Wie Sie sehen, wird beim Ausführen des Programms wie es ist die erste catch-Klausel ausgeführt (was wahrscheinlich das ist, was Sie ursprünglich gar nicht wollten).
2) Obwohl der in der ersten catch-Klausel abgefangene Typ vom Typ ist
std::exception
, wird die "richtige" Version vonwhat()
aufgerufen - weil er als Referenz abgefangen wird (ändern Sie mindestens denstd::exception
Typ des abgefangenen Arguments so , dass er nach Wert ist - und Sie werden das erleben "Object Slicing" -Phänomene in Aktion).3) Für den Fall, dass der "Code aufgrund der Tatsache, dass eine XXX-Ausnahme ausgelöst wurde ..." wichtige Dinge in Bezug auf den Ausnahmetyp tut, liegt hier ein Fehlverhalten Ihres Codes vor.
4) Dies ist auch relevant, wenn die gefangenen Objekte "normale" Objekte waren wie:
class Base{};
undclass Derived : public Base {}
...5) Unter
g++ 7.3.0
Ubuntu 18.04.1 wird eine Warnung ausgegeben, die auf das erwähnte Problem hinweist:Auch hier möchte ich sagen, dass diese Antwort nur ist ADD beschrieben hier zu den anderen Antworten (dachte ich , dieser Punkt ist erwähnenswert, doch konnte es nicht innerhalb eines Kommentars zeigen).
quelle