verständnisfrage zu Referenz auf Pointer



  • void fooA(Base*& arg)       { ... } 
    void fooB(Base* const& arg) { ... } 
    ...
    //Derived ist Spezialisierung von Base!
    Derived* derivedPtr = new Derived;
    
    fooA(derivedPtr); //error
    fooB(derivedPtr); //funzt
    

    Frage:
    Wieso? Liegt es daran, dass Derived* eben nicht vom Typ Base* ist?

    Ist das ähnlich wie bei:

    void fooA(int& a)        { ... } 
    void fooB(int const & a) { ... } 
    ...
    fooA(1); //error, da 1 nicht "änderbar" ist
    fooB(1); //funzt
    

    Zerbrechen uns hier grad den Kopf darüber 😉 Bitte helft 5 Ingenieuren...


  • Mod

    Ein X aus Derived hat nichts mit X aus Base zu tun (substituiere X mit "Zeiger auf", "Templateklasse mit Argument" etc.). Zwar kann einem Zeigerwert (also einer Adresse) auf ein Derived-Objekt der Zeigerwert auf das in Derived befindliche Base-Subobjekt zugeordnet werden. Das sagt aber nichts über die Zeigerobjekte des jeweiligen Typs aus.

    struct Base { ... };
    struct Derived1 : Base { ... };
    struct Derived2 : Base { ... };
    void foo(Base*& arg) { arg = new Derived2(...); }
    
    Derived1* derivedPtr;
    foo(derivedPtr); // nehmen wir an, das wäre möglich
    // ups, derivedPtr zeigt plötzlich auf ein Derived2 (eigentlich: das Base-Objekt davon, denn bei der Zuweisung in foo hat eine Konvertierung in Base* stattgefunden)
    

    fooB kann dagegen aufgerufen werden, hier wird ein temporäres Objekt des Typs Base* erzeugt (mit dem Zeigerwert, der durch die Konvertierung Derived->Base entsteht) und an die Referenz gebunden.



  • Okay. Ich glaub ich hab die Erklärung.

    Folgendes ist erlaubt (wenn auch nicht wirklich schön)

    void fooA(Base*& arg)       
    { 
       arg = new Base; 
    }
    

    Somit würde fooA den Zeiger, der eigentlich ein DerivedPtr war in einen BasePtr ändern udn das darf nicht sein.

    ups.. gleichzeitig mit camper geantwortet.

    danke, wie immer!



  • wenn du dort Polymorphismus betreiben willst, solltest du es mal so versuchen

    void fooA(Base* arg)       { ... }
    ...
    //Derived ist Spezialisierung von Base!
    Derived derivedPtr;
    
    fooA(derivedPtr);
    

    das SOLLTE laufen,bin mir aber nicht 100% sicher.



  • klar, das letzteres funntkioniert. die frage trat auf, weil ein Kollege einen boost::shared_ptr auf eine abgeleitete Klasse per Referenz and eine Methode übergeben wollte, die ausschließlich Referenzen auf shared_ptr der basisklasse verwenden.
    Grund war hier, dass er sich den Overhead der Referenzzählung ersparen wollte, wie es bei einem call per value der Fall gewesen wäre



  • Wenn das funktionieren würde, könnte die Variable derivedPtr nach dem Aufruf plötzlich auf eine ganz andere Spezialisierung zeigen.

    void fooA(Base*& arg) { arg = new Derived4711; } 
    //...
    Derived* derivedPtr = new Derived;
    fooA(derivedPtr);
    //jetzt wäre derivedPtr urplötzlich ein Zeiger auf Derived4711
    //...
    

    //EDIT: Mist, viel zu spät



  • Kreppel schrieb:

    Wenn das funktionieren würde, könnte die Variable derivedPtr nach dem Aufruf plötzlich auf eine ganz andere Spezialisierung zeigen.

    void fooA(Base*& arg) { arg = new Derived4711; } 
    //...
    Derived* derivedPtr = new Derived;
    fooA(derivedPtr);
    //jetzt wäre derivedPtr urplötzlich ein Zeiger auf Derived4711
    //...
    

    jupp... hab ich ja vor zwei posts geschrieben 😉



  • muffmolch schrieb:

    jupp... hab ich ja vor zwei posts geschrieben 😉

    Ja, das nächste Mal werde ich auf Refresh oder auf Vorschau drücken, wenn ich beim Schreiben so lange Pause mache... 🙄



  • Kreppel schrieb:

    muffmolch schrieb:

    jupp... hab ich ja vor zwei posts geschrieben 😉

    Ja, das nächste Mal werde ich auf Refresh oder auf Vorschau drücken, wenn ich beim Schreiben so lange Pause mache... 🙄

    das problem kenne ich... kein problem


Anmelden zum Antworten