Frage zu zwei Klassen mit einer Referenz
-
Hallo zusammen, ich habe hier eine Aufgabe durch die ich nicht ganz durchblicke.
Die Ausgabe des Programms ist folgendes:
Basis
AbleitungDer Code ist folgender:
#include <iostream> using namespace std; class B{ public: virtual void eineMethode(){ cout << "Basis" << endl; } }; class A :public B{ public: void eineMethode(){ cout << "Ableitung" << endl; } }; int main(void){ try{ throw A(); } catch (B b){ b.eineMethode(); } try{ throw A(); } catch (B &b){ b.eineMethode(); } }Ich bekomme diesen Teil einfach nicht in meine Birne.
catch (B &b){ b.eineMethode(); }Wieso wird dort jetzt die Klasse A aufgerufen, obwohl ein B erzeugt wurde und die Methode von b.eineMethode aufgerufen wird?
Auch verstehe ich
throw A()leider nicht. Wozu soll das gut sein? Ist das nur zur Verwirrung? Es wird doch dort gar nichts angelegt, sondern nur der Standardkonstruktor ohne Parameter aufgerufen - sehe ich das richtig?
Hoffe meine Frage ist einigermaßen klar. Es ist schwer sich korrekt auszudrücken.
Gruß
-
Hallo
Shizophren schrieb:
Wieso wird dort jetzt die Klasse A aufgerufen, obwohl ein B erzeugt wurde und die Methode von b.eineMethode aufgerufen wird?
Die Bezeichner sind vielleicht verwirrend. A ist Ableitung, nicht Basis.
Es wird ein A erzeugt und kein B. Dieses A wird einmal als Referenz übergeben (und bleibt somit ein A) und einmal als Kopie (und wird daher zu B).Shizophren schrieb:
Auch verstehe ich
throw A()leider nicht. Wozu soll das gut sein? Ist das nur zur Verwirrung? Es wird doch dort gar nichts angelegt, sondern nur der Standardkonstruktor ohne Parameter aufgerufen - sehe ich das richtig?
Irgendwie musste ja in den catch-Block kommen...versteh die Frage nicht.
-
Shizophren schrieb:
Ich bekomme diesen Teil einfach nicht in meine Birne.
catch (B &b){ b.eineMethode(); }Wieso wird dort jetzt die Klasse A aufgerufen, obwohl ein B erzeugt wurde und die Methode von b.eineMethode aufgerufen wird?
Es wurde kein B erzeugt. Guck genau hin:
catch (B &b)
Das ist eine Referenz auf ein B-Objekt, kein B-Objekt. hinter der Referenz steckt aber das vom throw erzeugte A-Objekt und das virtual greift daher.Auch verstehe ich
throw A()leider nicht. Wozu soll das gut sein?
Es erzuegt ein A-Objekt.
Ist das nur zur Verwirrung?
Vermutlich auch, damit du lernst, wie Exceptions funktionieren.
Es wird doch dort gar nichts angelegt, sondern nur der Standardkonstruktor ohne Parameter aufgerufen - sehe ich das richtig?
Nein. Ein throw erzeugt tatsächlich ein Objekt.
Verstehst du den Code, wenn ich etwas vergleichbares mal ohne Exceptionhandling schreibe?
A a; B b = a; B & bref = a; b.eineMethode(); bref.eineMethode();
-
Hi, danke für eure Antworten!
Das kann ich nachvollziehen.A a; B b = a; B & bref = a; b.eineMethode(); bref.eineMethode();Noch blicke ich nicht ganz durch meinen Code:
try{ throw A(); } catch (B b){ b.eineMethode(); }Sehe ich das richtig, dass hier ein Objekt A erzeugt wird
throw A();aber auch ein Objekt B und davon wird dann die Methode eineMethode aufgerufen?
catch (B b){ b.eineMethode();
-
Shizophren schrieb:
Sehe ich das richtig, dass hier ein Objekt A erzeugt wird
throw A();aber auch ein Objekt B und davon wird dann die Methode eineMethode aufgerufen?
catch (B b){ b.eineMethode();A()erzweugt ein temporäres Objekt des Typs A.
throw A()nimmt dieses erzeugte Objekt, um ein (temporäres) Exceptionobjekt (des Typs A) durch Kopieren/Verschieben zu erzeugen (copy/move-elision ist möglich)
catch (B b)benutzt das Exceptionobjekt (des Typs A) um den Parameter des Handlers (also das Objekt b) des Typs B zu initialisieren. Dabei kommt der Copykonstruktor von B zum Einsatz, weil das Exceptionobjekt an dessen Parameter (des Typs const B&) gebunden werden kann.