Kopierkonstruktor mit vector auf rein virtuelle Klasse



  • Hallo,
    Folgendes Problem:

    Ich möchte einen Kopierkonstruktor für eine Klasse schereiben, welche einen vector mit Zeigern auf eine rein virtuelle Klasse besitzt.

    wäre diese nicht rein virtuell hätte ich folgenden Ansatz im Kopierkonstruktor:

    for (unsigned int i=0;i<orig.vector.size();i++)
    {
    MyClass *tmp = new MyClass;
    *tmp=*orig.vector[i];
    vector.push_back(tmp);
    
    }
    

    Leider kann ich den tmp Zeiger aber gar nicht erst erstellen, wenn es sich um eine rein virtuelle Klasse handelt.

    Wie kann ich dies also Implementieren ?

    Danke schonmal 🙂


  • Mod

    Du kannst den vector nicht so einfach ohne weiteres kopieren, weil du dafür die most-derived-objects kopieren müsstest, also die eigentlichen Objekte auf die der Zeiger zeigt. Dafür musst du schon eine virtuelle clone() -Funktion o.ä implementieren.



  • /* removed */


  • Mod

    Dein virtuelle Klasse braucht eine clone-Methode, d.h. eine Methode, die einen Zeiger auf eine Kopie des momentanen Objekts zurück gibt. Der Trick ist, wenn diese Methode selber virtual ist, dann bekommst du ein Objekt der passenden abgeleiteten Klasse. Der Rückgabetyp der virtuellen Methode braucht übrigens kein Basisklassenzeiger zu sein. Es ist durchaus erlaubt eine virtuelle Methode mit einer anderen Methode zu überschreiben, die einen spezialisierteren Zeigertyp zurück gibt. Die Clonemethode kann also in jeder Klasse den passenden Rückgabewert haben.

    Man kann auch noch einen Schritt weiter gehen (oder auch noch mehrere Schritte) und CRTP benutzen, um die clone-Methode zu implementieren und dabei Codeduplikationen zu vermeiden. Das wird beispielsweise hier erklärt:
    http://katyscode.wordpress.com/2013/08/22/c-polymorphic-cloning-and-the-crtp-curiously-recurring-template-pattern/
    (in dem Link wird als Einführung auch die einfache Methode, die ich im ersten Absatz angesprochen habe, erklärt)


  • Mod

    Es ist durchaus erlaubt eine virtuelle Methode mit einer anderen Methode zu überschreiben, die einen spezialisierteren Zeigertyp zurück gibt.

    Stichwort kovariante Rückgabetypen (engl. covariant return types).

    @SeppJ: Hast du dir den Link eigentlich mal angeschaut?


  • Mod

    Arcoth schrieb:

    @SeppJ: Hast du dir den Link eigentlich mal angeschaut?

    Nur überflogen. Gehe ich aufgrund deiner Frage Recht in der Annahme, dass da Blödsinn erzählt wird? Ich habe bloß Stichproben genommen, da es doch recht viel Text war zu einem Thema, welches ich sowieso schon kenne und daher nicht vollständig lesen wollte. Besagte Stichproben sahen aber nicht schlecht aus.


  • Mod

    Gehe ich aufgrund deiner Frage Recht in der Annahme, dass da Blödsinn erzählt wird?

    Nein. Mir war nur mulmig wegen dem Abschnitt, in dem die Nutzung von Makros für dieses Problem gepriesen wurde...
    Außerdem immer sowas wie "nur zu Darstellungszwecken", "das sollte in echtem Code nicht verwendet werden", usw. voll am heißen Brei vorbei- und potenzielle Fehler und suboptimale Implementierungsdetails wegreden. Außerdem wird die bessere C++03-Lösung zum Konstruktor-Forwarden (nämlich mit Funktionstemplates) nicht gezeigt (sondern eine Schlechtere, das ist der Punkt) und lediglich verlinkt, das ist dann aber schon alles von mir an den Haaren herbeigezogen... 🤡

    Außerdem wird in den Kommentaren deutlich, dass der Autor bspw. auch nicht wusste, dass virtuelle Basisklassen einen virtuellen Destruktor brauchen. Irgendwie gruselig, dass jemand dann so einen Artikel postet und dicke Hauer von den Mitlesern aufgesammelt um im Nachhinein ausradiert zu werden.
    Edit²: Stimmt wiederum nicht ganz:

    I’m aware of these things, I tried to just make the examples bare bones without any distractions, and when it concerns returning a pointer, the patterns in the article don’t just apply to C++11. Maybe I should have added in a virtual destructor though.

    Also so halb-pseudomäßiger-Code. Bin mir nicht sicher, was ich glauben soll. Aber der Kommentator hat Recht, so einige Anfänger werden das direkt so übernehmen...

    Edit: Nvm, für den TE wird es locker reichen, ist ja eine gute Erklärung.


Anmelden zum Antworten