dynamisch erzeugtes objekt der basisklass der abgeleiteten zuweisen



  • Hi,

    ich möchte einem objekt der Abgeleiteten Klasse ein Objekt der Basisklasse zuweisen. Das Basisklassen-Objekt wurde dynamisch angelegt.

    AbgeleiteteKlasse* test = static_cast<AbgeleiteteKlasse*>(ObjektBasisklasse);
    

    dem Objekt test der abgeleiteten klasse weise ich mittels set-methoden noch
    einige werte zu.

    test->setValue(x*y);
    

    Das funktioniert auch soweit bis das programm beendet wird. Dann bekomme ich eine Meldung dass der Heap beschädigt ist.
    Weise ich dem objekt test keine werte zu bekomme ich die Meldung nicht.
    Gehe ich recht in der Annahme dass man dynamisch erzeugte Objekte nicht so einfach dem abgeleiteten Objekt zuweisen kann? Falls ja wie macht man das dann?

    thx schonmal



  • Das hat wenig Sinn, denn die Basisklasse ist weniger als die abgeleitete Klasse. Dementsprechend kann ein Objekt der Basisklasse auch nicht über einen Zeiger auf die abgeleitete Klasse referenziert werden.
    Oder im OOP-Sprech: Ein Objekt einer abgeleiteten Klasse ist ein Objekt seiner Basisklasse, aber ein Objekt der Basisklasse ist kein Objekt einer von ihm abgeleiteten Klasse.



  • Das versteh ich jetzt nicht ganz. Es ist mir klar dass die basisklasse "weniger" ist. aber mit:

    AbgeleiteteKlasse* test = static_cast<AbgeleiteteKlasse*>(ObjektBasisklasse);
    

    weise ich eben der abgeleiteten klasse nur den teil der basisklasse zu.
    mit static cast konvertiere ich eben das basisklassenobjekt in ein abgeleitetes, objekt, oder etwa nicht?



  • xxmaxx schrieb:

    Das versteh ich jetzt nicht ganz. Es ist mir klar dass die basisklasse "weniger" ist. aber mit:

    AbgeleiteteKlasse* test = static_cast<AbgeleiteteKlasse*>(ObjektBasisklasse);
    

    weise ich eben der abgeleiteten klasse nur den teil der basisklasse zu.
    mit static cast konvertiere ich eben das basisklassenobjekt in ein abgeleitetes, objekt, oder etwa nicht?

    Du konvertierst einen Zeiger auf die Basisklasse in einer Zeiger auf die abgeleitete Klasse. Dadurch bekommt aber Dein Basisklasseobjekt nicht plötzlich auf magische Weise die fehlenden Teile der abgeleiteten Klasse (im Speicher ist nur das Basisklassenobjekt).



  • hmm ok. aber mein objekt der abgeleiteten klasse hat ja eben noch zusätzliche member. wie kann ich jetzt, nachdem ich dem abgeleiteten obj. das basisklassenobj. zugewiesen habe, auf diese member zugreifen und werte zuweisen?



  • Du hast überhaupt kein abgeleitetes Objekt - du hast nur einen Zeiger, der glaubt auf ein abgeleitetes Objekt zu zeigen. Und wenn du da auf die Elemente der Kindklasse zugreifst, erwischst du in Wirklichkeit Speicherbereiche, die dir nicht gehören (hier waren's wohl Verwaltungsdaten des Heap-Managers).
    Wenn du ein Objekt der abgeleiteten Klasse benötigst, solltest du auch so eins erzeugen.



  • xxmaxx schrieb:

    hmm ok. aber mein objekt der abgeleiteten klasse hat ja eben noch zusätzliche member. wie kann ich jetzt, nachdem ich dem abgeleiteten obj. das basisklassenobj. zugewiesen habe, auf diese member zugreifen und werte zuweisen?

    Gar nicht. Das sage ich ja die ganze Zeit. Deine Basisklasse hat die Member nicht. Auch wenn die mit einem Zeiger auf irgendeine abgeleitete Klasse auf Deine Basisklassenobjekt zeigst bleibt es trotzdem das Basisklassenobjekt.



  • ok da hab ich wohl was falsch verstanden 🙂

    vielen dank auch



  • Deswegen nimmt man für einen Downcast auch dynamic_cast. Da kann man nachher prüfen ob das überhaupt geklappt hat.



  • Braunstein schrieb:

    Deswegen nimmt man für einen Downcast auch dynamic_cast. Da kann man nachher prüfen ob das überhaupt geklappt hat.

    Das geht aber nur, wenn man mit der Basisklasse auf ein Objekt der abgeleiteten Klasse zeigt. Wenn man nur ein Objekt der Basisklasse hat, hilft dynamic_cast reichlich wenig.



  • Tachyon schrieb:

    Das geht aber nur, wenn man mit der Basisklasse auf ein Objekt der abgeleiteten Klasse zeigt. Wenn man nur ein Objekt der Basisklasse hat, hilft dynamic_cast reichlich wenig.

    Wieso? Dann sollte doch 0 zurückgegeben werden.



  • Braunstein schrieb:

    Tachyon schrieb:

    Das geht aber nur, wenn man mit der Basisklasse auf ein Objekt der abgeleiteten Klasse zeigt. Wenn man nur ein Objekt der Basisklasse hat, hilft dynamic_cast reichlich wenig.

    Wieso? Dann sollte doch 0 zurückgegeben werden.

    Wird auch. Nur kann man dann bei der Überprüfung des cast Ergebnisses auch gleich if(false)... schreiben.



  • Tachyon schrieb:

    Wenn man nur ein Objekt der Basisklasse hat, hilft dynamic_cast reichlich wenig.

    Doch - wenn static_cast<> auf das falsche Objekt angewendet wird, erhältst du Müll, bei dynamic_cast<> bekommst du einen definierten Fehler (NULL-Zeiger bzw. bad_cast-Exception).



  • Braunstein schrieb:

    Deswegen nimmt man für einen Downcast auch dynamic_cast. Da kann man nachher prüfen ob das überhaupt geklappt hat.

    Ich nehme für Downcasts eigentlich immer static_cast . Und zwar weil ich in den Fällen, in denen ich downcaste, den Typ kenne. Wenn ich den Typ nicht kenne, versuche ich ihn nicht durch Typunterscheidungen herauszufinden. Daher finde ich dynamic_cast nur in Ausnahmefällen sinnvoll.



  • Hast du schonmal mit der VCL gearbeitet. Da brauchst du diesen cast schon manchmal. Das trifft auch auf andere Fremdlibs zu, wo du halt manchmal wirklich nur den Zeiger auf eine Basisklasse bekommst.
    Bei komplett selbst geschriebenen Sachen stimme ich dir aber zu.



  • Nein, mit der VCL habe ich keine Erfahrung. Kann durchaus sein, dass das manchmal vorkommt. Das bringt mich aber auf den Gedanken eines Dynamic-Dispatchers für unäre Funktionen, den ich mir vor einiger Zeit geschrieben habe:

    // In der Bibliothek festgelegt
    class A {...};
    class B : public A {...};
    class C : public A {...};
    
    A* GetBasePointer();
    
    // Eigene Funktionen für abgeleitete Typen
    void Function(B* b);
    void Function(C* c);
    
    int main()
    {
        // Objekt erstellen, das quasi Überladungen zur Laufzeit dispatcht
        SingleDispatcher<A*> sd;
        sd.Register<B>(&Function);
        sd.Register<C>(&Function);
    
        // Ruft automatisch richtige Funktion auf oder
        // wirft Exception, falls keine Entsprechung gefunden
        sd.Call( GetBasePointer() );
    }
    

    Manchmal ist ein simples dynamic_cast vielleicht einfacher, aber gerade wenn man viele Typen hat, kann sich der Dynamic-Dispatch lohnen.


Log in to reply