Im Kopierkonstruktor auf den Standard-Kopierkonstruktor zugreifen?



  • Hallo,

    ich habe eine Structure definiert, die neben sehr vielen Variablen auch einen Pointer beinhaltet. Das Objekt auf welches der Pointer zeigt, möchte ich gerne kopieren - und nicht nur dessen Zeiger.

    Ich hab das soweit auch kapiert, wie man das mit dem Kopierkonstruktor macht, aber es erscheint mir umständlich, alle (anderen) Variablen nochmals anzuführen, also das hier:

    Klasse(const Klasse& k)
    {a=k.a;
    b=k.b;
    c=k.c;
    d=k.d;
    //... geht das einfacher?
    }
    

    Meine Frage ist also: Gibt es irgendeine Möglichkeit im eigenen Kopierkonstruktor zunächst den Standardkopierkonstruktor zur Kopie aller Variablen zu verwenden, um sich danach dann um die Pointer zu kümmern?

    Oder gibt es eine andere Möglichkeit wie man elegant alles, was in der Structuredefinition steht, zu kopieren?

    Danke für die Hilfe!
    maugli



  • Betrifft die Frage wirklich C++/CLI oder doch etwa einfach c++?



  • In C++ 11 geht das meines Wissens 😉

    Es gibt aber auch eine andere Möglichkeit, die ich bei mir gern nutze.
    Ich packe einfach alle Membervariablen in eine Struktur. Die kann ich dann relativ leicht kopieren.

    Bsp:

    [cpp]
    class A
    {
      struct TData
      {
        int a;
        int b;
        int c;
        int d; //....usw.
      } m_Data;
    
      A(const A &src) : m_Data(src.m_Data)
      {
      }
    };
    [/cpp]
    

    Das funzt natürlich nur, wenn in m_Data keine Zeiger sind, um die müsste man sich noch kümmern. 😉



  • Danke Burkhi für Deine Antwort. Ich will die Sache deswegen nicht (weiter) verschachteln, da die Klasse, um die es geht, eigentlich eine Structure ist, deren Variablen an ungelogen 200 Stellen im Programm schon verwendet werden, die dann geändert werden müssten...

    Da ich das mit den Erbschaften noch nicht ganz kapiere, hier nochmal die genaue Frage: Würde das folgende also funktionieren?

    class Klasse
     {int a, b, c, d;
     int * e;
    
      Klasse()
       {e=new int;
       }
    
      ~Klasse()
       {delete e;
       }
    
      Klasse(const Klasse& k) : Klasse(k)
       {*e=*(k.e); 
       }
     }
    

    Falls ja, was ich dann auch nicht ganz verstehe: Der Standard-Kopierkonstruktor wird ja automatisch bereitgestellt. Durch meine Definition eines eigenen (erweiterten) Kopierkonstruktors in der Klasse... ...überschreibe ich den Standard-Kopierkonstruktor, oder wie ist das? Warum kann ich dann noch darauf zugreifen?
    Bzw.: In anderen Funktionen dieser Klasse: Wie kann ich dann unterscheiden, ob ich *meinen* erweiterten Kopierkonstruktor, oder den Standard-Kopierkonstruktor nutzen will?

    Danke für die Hilfe!
    maugli



  • Dieser Thread wurde von Moderator/in Jochen Kalmbach aus dem Forum C++/CLI mit .NET in das Forum C++ (auch C++0x und C++11) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Hi,
    wenn du den Kopierkonstruktor selbst definiert, dann wird der Standard Kopierkonstruktor nicht mehr automatisch erstellt und du musst die Kopierei selber machen.

    Um die Membervariablen zu kopieren,geht es aber auch so (grad ausprobiert):

    [cpp]
    class Test
    {
    public:
     int a,b,c,d;
    
     Test(){}
     Test(const Test &scr){*this = scr;}
    }
    [/cpp]
    

    Edit: Aber wie gesagt, um Zeiger muss du dich weiterhin selber kümmern, sonst würde einfach der Zeiger von src übernommen werden und die würden dann auf denselben Speicherbereich zeigen. Da muss du dann noch kopieren. 😉



  • Ich frage nochmal anders: Ich will den Standard-Kopierkonstruktor eben nicht neu schreiben, sondern nur um die gewünschte Funktionalität (hier: die Behandlung der Objekte, auf die mit Pointern gezeigt wird) erweitern. Wie greift man auf den Standard-Kopierkonstruktor innerhalb der Funktion meines Beispiels ("Klasse(const Klasse& k)") zu?

    Danke 🙂
    maugli



  • Ich rate dir dringend, den Zeiger loszuwerden, da du mit dynamisch allozierten Membern offensichlich noch nicht klarkommst. Du verletzt die Regel der großen Drei und in deinem Kopierkonstruktor machst du absoluten Blödsinn. Zeigt dein Zeiger auf einen einzigen int? Warum dann ein Zeiger? Falls es ein Feld ist, ersetze es durch std::vector. Dann brauchst du auch keinen Kopierkonstruktor mehr zu definieren (der von Burkhi ist übrigens überflüssig).



  • maugli schrieb:

    Wie greift man auf den Standard-Kopierkonstruktor innerhalb der Funktion meines Beispiels ("Klasse(const Klasse& k)") zu?

    Gar nicht. Verpack deine Zeiger in Smartpointer, damit du keinen eigenen Kopierkonstruktor brauchst.



  • Ich habe eine ähnliche Problematik zur Zeit auf Arbeit, wo wir teils recht große C-Strukturen neuerdings mit C++-Elementen angereichert haben. Das führt dazu, dass default-Initialisierung der Klassen plötzlich nicht mehr zur Null-Initialisierung der alten C-Elemente führt. Meine Lösung:

    struct someStuff_pod
    {
      int a;
      int b;
      int c;
      double d;
      /* usw. */
    };
    
    struct some_Stuff : someStuff_pod
    {
      std::vector<int> nonPOD;
    
      someStuff() : someStuff_pod() // <- default-Initialisierung fuers POD - alles ausgenullt :)
                  , nonPOD(4) 
       {}
    
      someStuff(someStuff const& rhs)
        : someStuff_pod(rhs) //trivial POD-copy :)
        , nonPOD(/*something non-trivial here*)
      {}
    };
    

    Ich habe also an das alte C-Struct einfach ein _pod an den Namen gehängt, das neue non-POD mit dem alten namen ausgestattet und kann jetzt immernoch auf die ganzen alten member wie gewohnt zugreifen, ohne den halben Code ändern zu müssen... Könnte bei dir auch helfen 😉



  • Erstmal Danke für die Antworten!

    @Burkhi: Das mit dem "=" im Kopierkonstruktor habe ich auch schon ausprobiert, aber damit verlagert man die Thematik ja nur auf den Operator=.. Dort ist es dann dasselbe Problem, wenn man das referenzierte Objekt durch ein = eben auch geklont haben möchte.

    @Michael E.: Ich stelle Fragen, damit ich es verstehe. Mein Beispiel ist nur ein Beispiel, um zu verdeutlichen, was ich möchte. In meinem Programm geht es statt eines int* um einen Pointer auf eine Objekt einer anderen Klasse. Aber das ist fürs Prinzip ja egal. Okay, das Beispiel ist nach der "Regel der großen Drei" unvollständig, weil der =operator fehlt. Ist aber kein Grund, mir die Pointer gleich ganz ausreden zu wollen 😉

    @mfk: Ohne Smartpointer geht es nicht?

    @pumuckl: Danke für den Tipp, der wird noch hilfreich sein!

    @alle: Mit euren Hinweisen nochmal anders formiliert: Wenn man den Kopierkonstruktur einer Klasse also definiert, ist der Standard-Kopierkonstruktor wirklich weg und man kommt nicht mehr dran? Ist das so?



  • maugli schrieb:

    Wenn man den Kopierkonstruktur einer Klasse also definiert, ist der Standard-Kopierkonstruktor wirklich weg und man kommt nicht mehr dran? Ist das so?

    Spielt keine Rolle, ob es ein Kopie-Konstruktor oder ein normaler ist. Sobald du einen Konstruktor deklarierst, erzeugt der Compiler keinen Standard-Konstruktor mehr. Folglich: Du definierst keinen Standard-Konstruktor und der Compiler macht es auch nicht, dann gibt es eben keinen.



  • Michael E. schrieb:

    ...(der von Burkhi ist übrigens überflüssig).

    Ja klar, wenn er nur die Membervariablen kopieren will, keine Frage. Aber er wollte ja auch die Zeiger mitkopieren und die Inhalte, auf die die Zeigen, so hab ich das zumindest verstanden. Und dann könnt er in diesen Kopierkonstruktor die entsprechenden Aufgaben erledigen. 😉



  • maugli schrieb:

    @Michael E.: Ich stelle Fragen, damit ich es verstehe. Mein Beispiel ist nur ein Beispiel, um zu verdeutlichen, was ich möchte. In meinem Programm geht es statt eines int* um einen Pointer auf eine Objekt einer anderen Klasse. Aber das ist fürs Prinzip ja egal. Okay, das Beispiel ist nach der "Regel der großen Drei" unvollständig, weil der =operator fehlt. Ist aber kein Grund, mir die Pointer gleich ganz ausreden zu wollen 😉

    Und dein Kopierkonstruktor ist falsch.

    Lass es mich mal anders formulieren: Welche Vorteile versprichst du dir von Pointern? Welche Vorteile versprichst du dir von new und delete?



  • @Gugelmoser: Danke Dir! Also bleibt mir wohl nichts viel anderes übrig, als die Variablen (wie von pumuckl vorgeschlagen) der Structure nochmals einzukapseln, damit ich sie ohne Umstände alle auf einmal kopieren kann? Versuch:

    class Klasse_alt
     {int a, b, c, d;
     int * e;
     }
    
    class Klasse : Klasse_alt
    {
       Klasse() {e=new int;}
    
      ~Klasse() {delete e;}
    
      Klasse(const Klasse& k)
       {Klasse_alt(k);     // das ist dann der "einfache" Kopierkonstruktor?
       e=new int;
       *e=*(k.e); 
       }
    
       Klasse& operator= (const Klasse& k)
       {if (this == &k) return *this;
       else {Klasse_alt(k);
            *e=*(k.e);
            return *this;
            }
       }
    }
    

    Stimmt das nun so ungefähr?



  • Einfach alles mit memcpy rüberschaufeln und dann um den Pointer kümmern.
    Vorrausgesetzt es handelt sich um PODs.



  • maugli schrieb:

    Stimmt das nun so ungefähr?

    Nein. Deine Vererbung ist privat und im Kopierkonstruktor und Zuweisungsoperator erstellst du Objekte der Klasse Klasse_alt, die du direkt wieder verwirfst.

    Ich denke immer noch, dass man dir am besten helfen kann, wenn du meine Fragen von eben beantwortest.



  • maugli schrieb:

    Stimmt das nun so ungefähr?

    class Klasse_alt
    {
    	protected:
    		int a, b, c, d;
    };
    
    class Klasse_neu : private Klasse_alt
    {
    	private:
    		int* e;
    
    	public:
    		Klasse_neu() : Klasse_alt(), e(new int)
    		{}
    
    		Klasse_neu(const Klasse_neu& ori) : Klasse_alt(ori), e( new int(*(ori.e)) )
    		{}
    
    		~Klasse_neu()
    		{
    			delete e;
    		}
    
    		Klasse_neu& operator=(const Klasse_neu& ori)
    		{
       			if(this == &ori) return *this;
       			Klasse_alt::operator=(ori);
       			*e = *(ori.e);
            	return *this;
            }	
    };
    

    Meinst du sowas?



  • Hey Michael,

    es mag sein, daß die Verwendung von Pointern in meiner Anwendung nicht erforderlich oder sinnvoll ist.

    Davon aber mal abgesehen: Damit ich was über Pointer lerne, möchte ich das erstmal so umsetzen, wie ich es im Codebeispiel illustriert habe. So wild ist es ja nicht: Ein Objekt mitsamt seinen Objekten (auf die gezeigt wird) herumkopieren können, ohne alle Member, die über den Standardkonstruktor kopiert werden können, für abtippen zu müssen.

    Ich denke schon, daß Du verstehst, was ich mit dem Code, den ich gepostet habe, machen will. Wenn Du mir zeigst, wie er in diesem Sinne funktionsfähig werden könnte, wäre das für mein Verständnis hilfreich.

    Viele Grüße,
    maugli



  • vielen dank gugelmoser! werde versuchen, das zu durchschauen 🙂


Log in to reply