Exception Handling, Vererbung und Polymorphie
-
Hallo!
Ich will gerade ein Exception Handling für ein Projekt implementieren und würde dabei gern einen catch-Block schreiben, der alle Fehler die zu einer Gruppe gehören fängt und mir dann sagt, welcher Fehler der Gruppe es ist. Code-mäßig habe ich mir das wie folgt vorgestellt:
#include <iostream> class UnspecifiedError { public: virtual const char* getType() { return "UnspecifiedError"; }; }; class SpecifiedError1 : public UnspecifiedError { public: const char* getType() { return "SpecifiedError1"; }; }; class SpecifiedError2 : public UnspecifiedError { public: const char* getType() { return "SpecifiedError2"; }; }; int main() { UnspecifiedError e1; SpecifiedError1 e2; SpecifiedError2 e3; try { throw(e1); } catch(UnspecifiedError e) { std::cout << e.getType() << std::endl; } try { throw(e2); } catch(UnspecifiedError e) { std::cout << e.getType() << std::endl; } try { throw(e3); } catch(UnspecifiedError e) { std::cout << e.getType() << std::endl; } return 0; }Die Ausgabe ist dann aber erwartungsgemäß
UnspecifiedError UnspecifiedError UnspecifiedErrorDie gewünschte Ausgabe ist aber
UnspecifiedError SpecifiedError1 SpecifiedError2Im catch-Block fange ich ja nunmal das konkrete Objekt und nicht einen Zeiger mit dem man dann Polymorphie betreiben könnte.
Hat jemand eine gute Idee, wie man etwas derartiges bewerkstelligen könnte? Gibt es dazu schon Lösungen?
Vielen Dank und viele Grüße,
Maik
-
Indem du einfach nicht ganze Objekte, sondern die Adresse der Objekte mit throw wirfst du den catch-Block anpasst.

-
versuch es mal mit virtual
-
#include <iostream> class UnspecifiedError { public: virtual const char* getType() { return "UnspecifiedError"; }; }; class SpecifiedError1 : public UnspecifiedError { public: virtual const char* getType() { return "SpecifiedError1"; }; // virtual }; class SpecifiedError2 : public UnspecifiedError { public: virtual const char* getType() { return "SpecifiedError2"; }; // virtual }; int main() { try { throw UnspecifiedError(); } catch(UnspecifiedError& e /* REFERENZ! & */) { std::cout << e.getType() << std::endl; } try { throw SpecifiedError1(); } catch(UnspecifiedError& e /* REFERENZ! & */) { std::cout << e.getType() << std::endl; } try { throw SpecifiedError2(); } catch(UnspecifiedError& e /* REFERENZ! & */) { std::cout << e.getType() << std::endl; } return 0; }
-
Dumme Frage am Rande: Polymorphie funktioniert doch nur bei Dynamischen Objekten?
-
Vielen Dank für eure super-schnellen Antworten.
Ich habe die zwei getType()-Funktionen virtuell gemacht und jetzt folgende main-Funktion, die eure Vorschläge umsetzt (und die gewünschte Ausgabe liefert).
int main() { UnspecifiedError e1; try { throw(&e1); } catch(UnspecifiedError* e) { std::cout << e->getType() << std::endl; } try { SpecifiedError1 e2; throw(&e2); } catch(UnspecifiedError* e) { std::cout << e->getType() << std::endl; } try { throw(&SpecifiedError2()); } catch(UnspecifiedError* e) { std::cout << e->getType() << std::endl; } try { throw(SpecifiedError2()); } catch(UnspecifiedError& e) { std::cout << e.getType() << std::endl; } return 0; }Die erste Zeile ist die direkte Umsetzung von Physik0r's Vorschlag.
Für die dritte Zeile bekomme ich die Warnung, das ich eine Referenz auf ein temporäres Objekt werfe. Aber ist passiert das nicht auch in Zeile 2 und 4 auch (zumal der catch-Block später auch in einer anderen Funktion stehen soll als der try-Block)?
Polymorphie muss ich mir wohl nochmal anschauen, ich dachte das geht nur im Zusammenhang mit Zeigern...
Noch eine letzte Frage, warum ist das virtual in den abgeleiteten Klassen nötig? Reicht nicht für Polymorphiy das virtual in der Basisklasse?
Grüße, Maik
-
Ja, das virtual reicht in der Oberklasse, wie du es bei deinem Eingangsposting gemacht hast.
Meiner Meinung nach sollte man das virtual allerdings auch in den Unterklassen wiederholen, damit jemand, der nur die Unterklassen sieht, weiß, was Sache ist.
Fehler wirft man als Objekte (wie in deinem ersten Beispiel) und fängt sie als Referenzen. Also:
int main() { UnspecifiedError e1; SpecifiedError1 e2; SpecifiedError2 e3; try { throw e1; } catch(UnspecifiedError &e) { std::cout << e.getType() << std::endl; } try { throw e2; } catch(UnspecifiedError &e) { std::cout << e.getType() << std::endl; } try { throw e3; } catch(UnspecifiedError &e) { std::cout << e.getType() << std::endl; } return 0; }Oder auch gleich so:
int main() { try { throw UnspecifiedError(); } catch(UnspecifiedError &e) { std::cout << e.getType() << std::endl; } try { throw SpecifiedError1(); } catch(UnspecifiedError &e) { std::cout << e.getType() << std::endl; } try { throw SpecifiedError2; } catch(UnspecifiedError &e) { std::cout << e.getType() << std::endl; } return 0; }Stefan.