try catch Verständnisfrage
-
Hallo,
ich beschäftige mich gerade mit try-catch, weiß jedoch
nicht was bei Catch (runden Klammern) gemacht wird.
Vorallem warum mit "&" die abgeleitete Klasse aufgerufen wird..
bzw. was fängt der catch?
Anbei der Code.
Ich habe soweit nach meinem Wissen kommentiert..class B{ public: virtual void eineMethode(){ cout << "Basis-Klasse" << endl; } }; class A : public B{ public: void eineMethode(){ cout << "abgeleitete Klasse" << endl; } }; int main(){ try{ // try-Exeption für das Exeption-Handling throw A(); // throw-Anweisung löst eine Exeption aus } catch (B b) { // FEHLT b.eineMethode(); // Methode der (Basis-)Klasse wird aufgerufen, } // wenn Exeption auftretet try{ throw A(); } catch (B& b){ // FEHLT b.eineMethode(); // Methode der (abgeleiteten-)Klasse wird aufgerufen, } // wenn Exeption auftretet return 0; }Ausgabe:
Basis-Klasse
abgeleitete Klasse
-
Deine Schwierigkeit ist nicht beim try..catch (das vielleicht auch, aber für deine Frage ist das erst einmal egal), sondern bei der Polymorphie (oder auch Vererbung im Allgemeinen). Wenn du einem Objekt der Basisklasse ein Objekt einer abgeleiteten Klasse zuweist (Zuweisung kann hier durchaus auch bedeuten, ein neues Objekt als Kopie zu erzeugen), gehen die Eigenschaften der abgeleiteten Klasse verloren. Wo sollten sie auch hin? Das Objekt der Basisklasse kann diese schließlich nicht aufnehmen. Das nennt sich "slicing".
Eine Referenz oder ein Zeiger auf ein Objekt können aber durchaus auf ein Objekt einer abgeleiteten Klasse zeigen. Und Polymorphie erlaubt dann dem Objekt, sich durchaus wie ein Objekt der abgeleiteten Klasse zu verhalten, selbst wenn es über einen Basisklassenzeiger angesprochen wird.Dein Beispiel ist eine Demonstration für den Leitspruch "throw by value, catch by reference".
Demonstration von Polymorphie ohne try..catch:
#include <iostream> using namespace std; class A{ public: virtual void eineMethode(){ cout << "Basis-Klasse" << endl; } }; class B : public A{ public: virtual void eineMethode(){ cout << "abgeleitete Klasse" << endl; } }; int main(){ A a; B b; a.eineMethode(); b.eineMethode(); A *aptr = &a; aptr->eineMethode(); aptr = &b; aptr->eineMethode(); A &aref = a; aref.eineMethode(); A &aref2 = b; aref2.eineMethode(); A acopy = a; acopy.eineMethode(); acopy = b; acopy.eineMethode(); }Schlag also am besten noch einmal Vererbung, Polymorphie und Slicing nach. try..catch ist dann nicht großartig anders als ein Funktionsaufruf es wäre:
#include <iostream> using namespace std; class A{ public: virtual void eineMethode(){ cout << "Basis-Klasse" << endl; } }; class B : public A{ public: virtual void eineMethode(){ cout << "abgeleitete Klasse" << endl; } }; void do_something_by_value(A acopy) { acopy.eineMethode(); } void do_something_by_reference(A &aref) { aref.eineMethode(); } int main(){ A a; B b; do_something_by_value(a); do_something_by_value(b); do_something_by_reference(a); do_something_by_reference(b); }In diesem Beispiel ist nichts anders als in dem vorherigen Beispiel. Beim Aufruf der Funktion wird entweder das Objekt kopiert (Variante 1) oder eben eine Referenz mit einem Verweis auf den Parameter initialisiert (Variante 2). Man kann das auch noch einmal mit Pointern machen, aber das spare ich mir mal, da in C++ unüblich und für try..catch irrelevant (es sei denn, du schmeißt einen Pointer auf ein Objekt, was zwar möglich, aber auch unüblich wäre).
P.S.: Ich habe A und B in deinem Code vertauscht, weil ich es sehr unintuitiv fand, dass A von B erbt. Außerdem ist deine Syntax zur Vererbung falsch gewesen.
-
danke für die verständliche Erlärung.
Ich habe mir die Themen nochmal angeschaut und mir ist jetzt klarer geworden