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
    Ableitung

    Der 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.


  • Mod

    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();
    

  • Mod

    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.


Anmelden zum Antworten