Klasse mit Erbungen kopieren



  • Hallo,

    Kann eine Klasse, samt all seine Erbungen kopiert werden? Falls ja, wie?

    Dankeschön!



  • Ja


  • Administrator

    #include <vector>
    #include <algorithm>
    
    class Base
    {
      std::vector<int> m_data;
    
    public:
      virtual ~Base() { }
    
      Base& operator =(Base base)
      {
        base.swap(*this);
        return *this;
      }
    
      virtual Base* clone() const
      {
        return new Base(*this);
      }
    
      void swap(Base& base)
      {
        using std::swap;
        swap(m_data, base.m_data);
      }
    };
    
    void swap(Base& lhs, Base& rhs)
    {
      lhs.swap(rhs);
    }
    
    class Derived
      : public Base
    {
    public:
      Derived& operator =(Derived derived)
      {
        derived.swap(*this);
        return *this;
      }
    
      virtual Derived* clone() const
      {
        return new Derived(*this);
      }
    
      void swap(Derived derived)
      {
        Base::swap(derived);
      }
    };
    
    void swap(Derived& lhs, Derived& rhs)
    {
      lhs.swap(rhs);
    }
    
    int main()
    {
      Base b0;
      Base b1;
      b1 = b0; // funktioniert.
    
      Derived d0;
      Derived d1;
      d0 = d1; // funktioniert, Base wird auch kopiert.
    
      Base* pb = &d0;
    
      Base* pc = pb->clone(); // Kopie anfordern, Derived wird auch kopiert.
      delete pc; // <- nicht vergessen.
    
      return 0;
    }
    

    Von der Methode über clone rate ich allerdings ab. Es ist meistens nicht nötig, wenn man die Objekte nicht unnötig Upcastet und zudem ist es ungewohnt, dass man das Objekt plötzlich über delete freigeben muss.

    Grüssli



  • Dravere schrieb:

    zudem ist es ungewohnt, dass man das Objekt plötzlich über delete freigeben muss.

    deshalb bietet man ja auch eine (statische) destruct-Methode an?!

    bb


  • Administrator

    unskilled schrieb:

    Dravere schrieb:

    zudem ist es ungewohnt, dass man das Objekt plötzlich über delete freigeben muss.

    deshalb bietet man ja auch eine (statische) destruct-Methode an?!

    Wie bitte? Ein Base::destruct oder was? Was soll daran besser sein? Zudem hat man kein RAII.
    Es gibt ein paar Umsetzungen, welche eine Art von Smart Pointer zurückgeben und so auch RAII garantieren, allerdings finde ich auch diese Umsetzungen mehrheitlich seltsam. Zudem sind sie oft mit einiges an zusätzlicher Arbeit verbunden.

    Am besten gleich darauf verzichten, was man meistens auch ohne Probleme tun kann.

    Grüssli



  • Dankeschön!



  • Dravere schrieb:

    Zudem hat man kein RAII.

    stimmt - in deinem bsp mit dem clone/delete hat man das ja~~

    Dravere schrieb:

    Am besten gleich darauf verzichten, was man meistens auch ohne Probleme tun kann.

    Japp - aber wenn man schon clone anbietet und keine schlauen zeiger nimmt, sollte man auch eine fkt zum löschen anbieten...
    ich denke, ich würde es mit clone und destruct machen und nen pointer-typedef nehmen - damit man später auch nen smart-ptr oder so was in der art zurückgeben kann, wenn man sich dann darum kümmern möchte(bzw. nen eigenen pointer schreiben, falls man das für nötig halten sollte)...
    die destruct-fkt macht dann halt nichts mehr...

    bb


  • Administrator

    unskilled schrieb:

    Dravere schrieb:

    Zudem hat man kein RAII.

    stimmt - in deinem bsp mit dem clone/delete hat man das ja~~

    1. Ich habe nie behauptet, dass es in meinem Beispiel RAII hat.
    2. Ich empfehle meine Version ja auch nicht, ich rate davon auch ab.

    Mein Punkt war, dass das hinzufügen von eine Methode destruct überhaupt nix bringt, weil es immer noch kein RAII hat. Ob man nun delete aufruft oder über destruct geht, spielt eigentlich keine grosse Rolle. Es ist beides kein RAII.

    unskilled schrieb:

    ich denke, ich würde es mit clone und destruct machen und nen pointer-typedef nehmen - damit man später auch nen smart-ptr oder so was in der art zurückgeben kann, wenn man sich dann darum kümmern möchte(bzw. nen eigenen pointer schreiben, falls man das für nötig halten sollte)...
    die destruct-fkt macht dann halt nichts mehr...

    1. Dann hast du zwar vielleicht später mal RAII, aber verunsicherst die Benutzer der Klasse mit der destruct Methode.
    2. Wenn du genau hinsiehst, dann verwende ich kovariante Rückgabewerte. Das geht nicht so einfach mit Smart-Pointern. Also entweder müsstest du darauf von anfang an verzichten, was sehr blöd wäre, oder du hättest einen ziemlich heftigen Schnittstellenbruch nach der Modifikation, wodurch deine versuchte Rückwärtskompatibilität auch flöte gehen würde.

    Grüssli



  • ok - da hast du recht^^

    bb


Anmelden zum Antworten