Eigene Exception Klasse
-
Um bei einer selbst geworfenen Exception schnell den Code dazu zu finden haben wir uns eine eigene Exception Klasse erstellt.
Die Klasse selber wurde von std::runtime_error abgeleitet und beinhaltet zusätlich zum Fehlertext, den Dateinamen, die Zeilennummer und den Funktionsnamen in der die Exception aufgetretten ist.
Um diese Informationen automatisch zu ermitteln wird das werfen der Exception über ein Makro aufgerufen.
#define THROW_TRACEABLE_EXCEPTION(message) throw TraceableException::Create(message, __FILE__, __LINE__, __FUNCTION__);
Create() ist eine statische Methode die wiederum den Konstruktor der Klasse TraceableException aufruft und das Objekt zurück gibt.
(hätte auch gleich direkt den Konstruktor aufrufen können, aber ich habe ein paar Überladungen von Create die in manchen Fällen noch bestimmte Dinge vorher initialisieren)
Aber worum es mir nun geht ist, ob es richtig ist von runtime_error abzuleiten.
Ich weiß eigentlich sollte man nicht immer den selben Typ von exception werfen. Problem ist dass man dann in einer Methode nicht mehrere (unterschiedliche) Exceptions werfen kann, um darauf dann mit unterschiedlichen catch() Blöcken reagieren zu können.
Aber die exceptions die wir so werfen werden nur dazu verwendet um die Prozedur sauber zu unterbrechen / zu beenden und die Meldung an den Bediener und die zusätlichen Informationen an den Service auszugeben.
Nochmals zur Frage: Ableiten von runtime_error oder besser von std::exception.
Oder was soll der ganze sch*** mach doch besser ... !?
-
Aus The C++ Programming Language, 4th Edition von Bjarne Stroustrup, §30.4.1.1:
A programmer can define an exception by deriving from a standard-library exception like this:
struct My_error : runtime_error { My_error(int x) :runtime_error{"My_error"}, interesting_value{x} { } int interesting_value; };
Und §30.5:
The standard-library exception hierarchy can be (but does not have to be) used for a user's own exceptions; §30.4.1.1.
Es ist sehr in Ordnung von std::runtime_error abzuleiten.
Auch §30.4.1.1:
Logic errors [std::logic_error] are errors that in principle could be caught either before the program
starts executing or by tests of arguments to functions and constructors. Run-time errors [std::runtime_error] are all
other errors.std::runtime_error erbt direkt von std::exception. Die Exception-Hierarchie, die in <exception> definiert wird, dient zur zweckerfüllenden Nutzung, das heißt, dass du theoretisch irgendeine Klasse nutzen könntest, allerdings haben bestimmte Klassen bestimmte Bedeutungen und je nach Bedeutung solltest du die Klasse auch nutzen.
Wie im Zitat angegeben, sind std::logic_errors Exceptions, die zur Verifizierung der Korrektheit des Programs dienen. std::runtime_errors hingegen sollen alles andere, also Fehler zur Laufzeit signalisieren. Entscheide du nun, was besser passt, wir kennen dein Programm nicht. std::exception sollte aber nicht direkt verwendet werden, da du diese zwei Unterklassen, die durch ihre Namen den Code besser dokumentieren, bereitgestellt bekommst.Um etwas sauber zu unterbrechen... bist du dir sicher, dass Exceptions da das richtige sind? Nicht andere Kontrollstrukturen? Ich nutze Exceptions in ihrem namentlichen Sinne, nämlich als Ausnahmen. Wenn ich eine Exception werfe, dann tue ich dies, weil ein Ausnahmezustand eingetreten ist wie bei Fehlern, zum Beispiel. Was du wählst, ist letztendlich aber deine Sache. Erfahrung und die Meinungen Anderer werden dir den Weg zur Erleuchtung leiten.
Was fest steht, ist, dass du Exceptions nach ihrem Zweck unterteilen solltest. Du kannst auch einfach throw int{} schreiben, keiner hält dich davon ab. Es drückt die Intention deines Codes nur nicht sehr gut aus und außerdem willst du natürlich auch Metadaten in Exceptions speichern.Ich empfehle dir letztendlich, etwas, was funktioniert und die Intention deines Codes optimal ausdrückt zu wählen. Wäge anhand deines momentanen Wissens ab, ob du dich für eine Exception-Klasse oder mehrere, spezifische Klassen entscheidest. Sollte deine gewählte Methode auf Probleme stoßen, erwäge die andere. Ohne ganz konkret deinen Code zu sehen, können wir dir keinen definitiven Ratschlag geben. Mache ruhig die Erfahrung und schaue selbst, was gut funktioniert und was nicht.