Exception werfen
-
also danke für das Beispiel...sollte man immer eine eigene exception klasse bauen die von std erbt? Ist das sauberer als einfach nur eine throw runtime_error() und das bis in die oberste hierarchie durchzureichen wo dann ein exit() oder ähnliches steht?
-
Nexus schrieb:
anges schrieb:
war der meinung dass jede exception irgendwie zum programmterminierung führt?!?!?
Nein, wenn du sie mit
catchfängst, kannst du sie behandeln und das Programm weiterlaufen lassen, was auch sinnvoll ist. Also entweder nicht fangen, was in Release-Versionen zum Absturz (nicht normales Programmende) führen kann, oder explizit das Programm beenden, durchreturn,exit()oder auf die harte Tour mitterminate().k thx,
das programm sollte man dann mit etwa return mit dem wert > 0 beenden oder??
-
WeißBier schrieb:
also danke für das Beispiel...sollte man immer eine eigene exception klasse bauen die von std erbt? Ist das sauberer als einfach nur eine throw runtime_error() und das bis in die oberste hierarchie durchzureichen wo dann ein exit() oder ähnliches steht?
Der Vorteil einer eigenen Klasse ist ja, dass du die gesondert fangen kannst. Wenn schlussendlich alle Objekte nur runtime_error sind, dann kannst du da kein spezielles Ereignis fangen und darauf reagieren. Dir bleibt dann nichts anderes übrig, als das durchzureichen und irgendwann auszugeben, was ein wenig gegen den Sinn von exceptions wäre. Eine Hierarchie zu halten ( ob von den std abgeleitet oder nicht) ist bestimmt eine gute Idee.
-
anges schrieb:
k thx,
das programm sollte man dann mit etwa return mit dem wert > 0 beenden oder??Ja, zum Beispiel. Wobei das vor allem relevant ist, wenn du das Programm vom Betriebssystem aufrufst und einen Rückgabewert erwartest. Ansonsten kann es auch sehr sinnvoll sein, mittels
std::clogoderstd::cerrin eine Log-Datei zu schreiben.drakon schrieb:
Eine Hierarchie zu halten ( ob von den std abgeleitet oder nicht) ist bestimmt eine gute Idee.
Wobei ich es (für einen allfälligen Anwender) intuitiver finde, von
std::exceptionabzuleiten. Denn so ist es möglich, generisch auf Exceptions zu reagieren, da man mit demcatch(...)-Block nicht mehr an die Exception rankommt und andernfalls auch auf höchster Abstraktionsebene immer mehrere Typen fangen muss.
-
Nexus schrieb:
drakon schrieb:
Eine Hierarchie zu halten ( ob von den std abgeleitet oder nicht) ist bestimmt eine gute Idee.
Wobei ich es (für einen allfälligen Anwender) intuitiver finde, von
std::exceptionabzuleiten. Denn so ist es möglich, generisch auf Exceptions zu reagieren, da man mit demcatch(...)-Block nicht mehr an die Exception rankommt und andernfalls auch auf höchster Abstraktionsebene immer mehrere Typen fangen muss.Ich wollte mich da enthalten etwas zu empfehlen und von
std::exceptionabzuleiten, weil es schlussendlich imo wichtiger ist eine klare Struktur zu haben, als davon ableiten zu müssen. Ist halt auch wieder so eine ewige Frage.. Die einen mögen es, die anderen nicht.
-
WeißBier schrieb:
also danke für das Beispiel...sollte man immer eine eigene exception klasse bauen die von std erbt? Ist das sauberer als einfach nur eine throw runtime_error() und das bis in die oberste hierarchie durchzureichen wo dann ein exit() oder ähnliches steht?
Meine eigenen Exception Klassen erben nicht von std::exception. Ich hab sie davon getrennt. Wichtig ist das man hier einfach eine gute Vererbungsstruktur einhält, dh man baut sich ne Basisklasse und geht von da aus immer Spezialisierter los. Außerdem können Exceptions mehr mitnehmen als nur einen CSTring, man kann ihnen alles Mögliche an Daten für die Fehelranalyse mitgeben.
Nexus schrieb:
Wobei ich es (für einen allfälligen Anwender) intuitiver finde, von
std::exceptionabzuleiten. Denn so ist es möglich, generisch auf Exceptions zu reagieren, da man mit demcatch(...)-Block nicht mehr an die Exception rankommt und andernfalls auch auf höchster Abstraktionsebene immer mehrere Typen fangen muss.Ich dachte immer der catch(...) Block fängt alles auf was geflogen kommt?
-
Xebov schrieb:
Ich dachte immer der catch(...) Block fängt alles auf was geflogen kommt?
Ja, aber man hat keine Möglichkeit mehr, auf das geworfene Exception-Objekt zuzugreifen, da man den Typ nicht kennt und keinen Parameter hat.
-
Xebov schrieb:
Ich dachte immer der catch(...) Block fängt alles auf was geflogen kommt?
Eben das ist das Problem. Du weißt nur dass du was gefangen hast, nicht was du gefangen hast, kannst es also nicht weiterverwenden. Wenn du dagegen von std::exception abgeleitet hast kannst du immerhin noch what() aufrufen:
try { /* ... */ } catch(std::exception& e) { std::cerr << "Exception caught! Message: " << e.what() << std::endl; } catch(...) { std::cerr << "Caught something! Don't know what it is. Happy guessing!" << std::endl; }
-
Nexus schrieb:
man hat keine Möglichkeit mehr, auf das geworfene Exception-Objekt zuzugreifen
Wieso exception-Objekt? Da kann genausogut ein int, char* oder sonstwas geflogen kommen und ins Netz gehn

-
pumuckl schrieb:
Wieso exception-Objekt? Da kann genausogut ein int, char* oder sonstwas geflogen kommen und ins Netz gehn

Das sind Objekte (abgesehen von Referenzen).

-
ich hab das mal einfach mal übernommen:
#include <string> #include <exception> class ScriptException : public std::exception { // Attributes // private: int m_line; std::string m_message; // Constructors // public: ScriptException(std::string const& message, int line) : m_line(line) , m_message(message) { } // Methods // public: virtual const char* what() const { return m_message.c_str(); } std::string const& get_message() const { return m_message; } int get_line() const { return m_line; } };und bekomm beim compiliern aber ien paar fehlermeldungen....
ScriptException.cpp 24: error: looser throw specifier for 'virual const char* ScriptException::what() cont' ScriptException.cpp 6: error: looser throw specifier for 'virtual ScriptException::~ScriptException()'
-
pumuckl schrieb:
Eben das ist das Problem. Du weißt nur dass du was gefangen hast, nicht was du gefangen hast, kannst es also nicht weiterverwenden. Wenn du dagegen von std::exception abgeleitet hast kannst du immerhin noch what() aufrufen:
Ach so war das gemeint ok. Aber wenn ich nicht erben lasse, aber trotzdem eine Klare Linie einhalte geht das ja im Grunde auch.
Ich hab folgende Aufstellung in meiner Klasse:
class e_MyExceptionBase { Konstruktor(); Operator=; Destruktor; Copykonstruktor; const char* what() const; };Das is ein Schema meienr Basisklasse von ihr erben alle Kategorieklassen (wie Memory und Operation) die dann ihrerseits Basis für Detail Exceptions sind (OutOfMemory zb) und die sehen dann bei mir so aus:
class e_MyExceptionBase_Memory { Konstruktor(); Operator=; Copykonstruktor; };Funktioniert bei mir ganz gut und am ende können bei mir ja nur 2 exceptions rauskommen eine std::exception oder eine e_MyExceptionBase.
-
Hat es einen Grund, wieso du eigene Kopierkonstruktoren und Zuweisungsoperatoren definierst? Verwaltest du dynamischen Speicher oder sonstige Ressourcen in deinen Exceptions?
-
Nexus schrieb:
Hat es einen Grund, wieso du eigene Kopierkonstruktoren und Zuweisungsoperatoren definierst? Verwaltest du dynamischen Speicher oder sonstige Ressourcen in deinen Exceptions?
Ja. Meine Base Exception hat einen char* in dem die Nachricht liegt. Die ganzen erbenden klassen schleifen in ihrem operator= und Copykonstruktor alles zur Basisklasse durch.
-
Xebov schrieb:
Ja. Meine Base Exception hat einen char* in dem die Nachricht liegt. Die ganzen erbenden klassen schleifen in ihrem operator= und Copykonstruktor alles zur Basisklasse durch.
Warum kein std::string?
-
Shade Of Mine schrieb:
Xebov schrieb:
Ja. Meine Base Exception hat einen char* in dem die Nachricht liegt. Die ganzen erbenden klassen schleifen in ihrem operator= und Copykonstruktor alles zur Basisklasse durch.
Warum kein std::string?
Ich wolte unnötiges Speicherholen vermeiden. Hab mich mit den strings mal auseinandergesetzt, und gelesen das für die ausgabe das Strings als CString nochmal Speicher geholt wird um den CString zu bauen, das wollte ich so eigentlich nicht haben, weil ich auf de reinen seite einheitlich mit den exceptions aus der std cStrings ausgeben wolte und auf der anderen Seite auch eigene Exceptions schmeiße wenn ich ein std::bad_alloc auffange, weis nicht ob meine überlegung so Sinnvoll ist oder nicht, ich fand sie auf jedenfall nicht schlecht und hab sie deshalb so umgesetzt.
-
Xebov schrieb:
Ich wolte unnötiges Speicherholen vermeiden.
Dann schreib dir eine passende string klasse.
Man fasst rohen speicher einfach nicht haendisch an.
-
Shade Of Mine schrieb:
Xebov schrieb:
Ich wolte unnötiges Speicherholen vermeiden.
Dann schreib dir eine passende string klasse.
Man fasst rohen speicher einfach nicht haendisch an.
Der aufwand würde sich nicht lohnen. Der Konstruktor nimtm die Nachricht entgegen und holt den Speicher zum reinstopfen und der Destruktor gibt ihn wieder frei, ich sehe da ehrlich gesagt keinen wirklichen Grund für eine Extra Klasse die am Ende ja auch nichts anderes macht.
-
Shade Of Mine schrieb:
Xebov schrieb:
Ich wolte unnötiges Speicherholen vermeiden.
Dann schreib dir eine passende string klasse.
Man fasst rohen speicher einfach nicht haendisch an.
boar... es geht um exceptions - ich weiß ja nicht, wie ihr programmiert, aber bei mir ist es eher die ausnahme, dass exceptions fliegen - also muss ich mir da echt 0 gedanken um performance machen - weil das ohnehin meist heißt, dass irgendwas nicht geht/ging...
bb
-
Aua!!! Wer hat mir die Exception an den Kopf geworfen? Passt mal besser auf!!!
