Objekte kopieren



  • Dazu ist noch die Regel der "großen Drei" erwähnenswert, die besagt dass wenn eins der drei( Kopierkonstruktor, Zuweisungsoperator, Destruktor ) benötigt wird in der Regel auch die anderen beiden erforderlich sind. Ausnahme ist der virtuelle Destruktor der für die Polymorphie benötigt wird.

    Wie schon gesagt wurde reicht eg meistens die compilergenerierten Versionen der drei außer deine Klasse enthält zum Beispiel Zeiger.

    Lg freeG



  • wie sieht das jetzt aber bei einer Mehrfachvererbung aus?

    Ich habe jetzt mal in der Basisklasse den Kopierkonstruktor reingemacht und dann auch in jeder vererbten Klasse einen Kopierkonstruktor erstellt.

    Foo::Foo(const Foo &obj) : Bar(obj) {
    
    }
    

    Allerdings bekomme ich da dann immer die Fehlermeldung, dass der Konstruktor mehrfach deklariert wurde, da ich ja hier etwa falsch gemacht habe, allerdings weiß ich da gerade nicht was genau.

    Darf ich da den Kopierkonstruktor der Basisklasse bzw. Elternklasse nicht mehr mit aufrufen oder wie genau muss ich das machen?



  • fr33g schrieb:

    Ausnahme ist der virtuelle Destruktor der für die Polymorphie benötigt wird.

    Wobei es hier auch sinnvoll ist, Kopierkonstruktor und Zuweisungsoperator zu deklarieren – jedoch ohne Definition im private -Bereich, sodass sie nicht versehentlich aufgerufen werden.

    fr33g schrieb:

    Wie schon gesagt wurde reicht eg meistens die compilergenerierten Versionen der drei außer deine Klasse enthält zum Beispiel Zeiger.

    Auch Zeiger sind nur ein Problem, wenn sie das verwiesene Objekt besitzen. Wenn sie auf ein unabhängiges Objekt ausserhalb zeigen, tun die eingebauten Methoden das Richtige.

    anno schrieb:

    Allerdings bekomme ich da dann immer die Fehlermeldung, dass der Konstruktor mehrfach deklariert wurde, da ich ja hier etwa falsch gemacht habe, allerdings weiß ich da gerade nicht was genau.

    Zeig uns ein minimales aber vollständiges Codebeispiel, das den gezeigten Fehler immer noch repräsentiert.



  • Hier ist mal ein Vererbungsbeispiel.

    //Basisklasse
    class Foo {
    
    protected:
    bool is_active_foo;
    
    public:
    Foo(const Foo &obj);
    
    };
    
    Foo::Foo(const Foo &obj) {
    
    }
    
    //1. Vererbung
    class Bar : public Foo {
    
    protected:
    bool is_active_bar;
    
    public:
    Bar(const Foo &obj);
    
    };
    
    Bar::Bar(const Bar &obj) :
     		 Foo(obj) {
    
    }
    
    //2. Vererbung
    class Top : public Bar {
    
    protected:
    bool is_active_bar;
    
    public:
    Top(const Foo &obj);
    
    };
    
    Top::Top(const Top &obj) :
     		 Bar(obj) {
    
    }
    


  • Bei den abgeleiteten Kopierkonstruktoren stimmen die Funktionsdeklarationen nicht mit den -definitionen überein.



  • Du müsstest die Parameter der Deklaration so ändern dass sie mit denen deiner Definitionen übereinstimmen, sprich ihnen eine const Referenz auf den Typ des abgeleiteten Objekts geben und nicht auf die Basis.

    Lg freeG



  • Das hätte er auch selbst rausfinden können. 😉



  • Nexus schrieb:

    Das hätte er auch selbst rausfinden können. 😉

    Ja da hast du natürlich recht, aber ich dachte da er mit der Compilermeldung wohl nicht klar kam und er es hier gepostet hat erklär ichs auch kurz genau, nicht dass er die Definitionen abändert 😃 😉

    Lg freeG



  • Also das Kopieren der Klassen funktioniert soweit mal. Thx für die Hilfe.

    Allerdings habe ich auch Zeiger innerhalb der Klasse.

    //2. Vererbung
    class Top : public Bar {
    
    protected:
    EineAndereKlasse *obj0;
    bool is_active_bar;
    
    public:
    Top(const Foo &obj);
    
    };
    

    Diese ist einfach eine seperate Klasse die ich eingebunden habe. so wie es aussieht wird diese aber nicht mit kopiert. Wie bekomme ich das denn bei dieser hin, sie mit zu kopieren im Kopierkonstruktor?

    EineAndereKlasse *obj0;
    


  • Top(const Foo &obj);
    

    Das ist ja immer noch falsch. Lies nochmals meinen und fr33gs Beitrag. Und rücke bitte deinen Code ein, dann ist er um einiges übersichtlicher.

    Brauchst du wirklich Zeiger, oder geht auch ein

    EineAndereKlasse obj0;
    

    ?

    Falls du besitzende Zeiger benötigst (z.B. um Abhängigkeiten zu verringern), kommt es natürlich drauf an, wie ihr Speicher angefordert wurde. Da dies höchstwahrscheinlich mit new erfolgte, sollte der Kopierkonstruktor ebenfalls ein new verwenden:

    Top::Top(const Top& origin)
    : obj0(new EineAndereKlasse(*origin.obj0))
    // hier andere Member kopieren
    {
    }
    

    Der Destruktor muss dann mit delete freigeben und den Zuweisungsoperator implementierst du am besten mit Copy-and-Swap (such mal danach, auf Wikibooks ist das Idiom z.B. erklärt).



  • naja, dann braucht der Zeiger bzw. die Klasse, der in der Klasse erstellt wurde ja auch einen Kopierkonstruktor, ist das richtig?

    EineAndereKlasse *obj0;
    


  • Ich habe irgendwie dieses dumpfe Gefühl, dass du das alles noch nicht so wirklich verstehst 😉

    Schau mal der Compiler generiert immer automatisch einen Kopierkonstruktor, Zuweisungsoperator und Destruktor für eine erstellte Klasse, außer du definierst selber diese drei, dann macht es der Compiler nicht.

    So wenn jetzt deine Klasse einen besitzenden Zeiger auf ein anderes Objekt enthält und den Speicher mit new anfordert, dann musst du dies auch im Kopierkonstruktor und Zuweisungsoperator definieren. Zusätzlich musst du den Speicher auch im Desktruktor mit delete freigeben, genauso musst du beim Zuweisungsoperator dann ja auch die alten Werte löschen.

    So wenn jetzt dein Zeiger auf ne andere von dir erstellte Klasse zeigt, diese jedoch keine besitzenden Zeiger enthält, dann reichen eigentlich die vom Compiler generierten Varianten aus, so dass du da nichts machen musst.

    Hast du das verstanden?

    Lg freeG


Anmelden zum Antworten