Im Kopierkonstruktor auf den Standard-Kopierkonstruktor zugreifen?
-
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
-
maugli schrieb:
es mag sein, daß die Verwendung von Pointern in meiner Anwendung nicht erforderlich oder sinnvoll ist.
Du wirst besitzende rohe Zeiger als Member nie brauchen. Aber OK, du willst ja was lernen: Orientiere dich an dem Code von pumuckl. Beachte, dass er struct verwendet, während du class schreibst. Dadurch ist bei pumuckl die Vererbung public, während sie bei dir private ist. Außerdem hast du pumuckls Initialisierungsliste in den Kopierkonstruktor reingezogen, was du nicht machen solltest.
Du kannst auch den letzten Code von Gugelmoser betrachten, aber mach Member nicht protected und benutze keine private, sondern öffentliche Vererbung (beide Regeln haben wieder so gut wie keine Ausnahmen).
-
maugli schrieb:
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.
Überlasse des Kopieren am besten dem Compiler. Wenn Dir nicht passt, wie der Compiler ein Object der Klasse kopiert, dann überlege zunächst, ob Du nicht vielleicht einem Datenelement einen falschen Typ verpasst hast, statt in so einem Fall die Kopieroperationen und Destruktoren der "einhüllenden" Klasse ohne darüber nachzudenken, selbst zu definieren. Die Semantik eines rohen Zeigers ist offensichtlich nicht die, die Du haben willst.
maugli schrieb:
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,
Ja, das ist blöd. Das Problem ist wahrscheinlich durch ein besseres Design lösbar. Spricht etwas dagegen, statt des Zeigers das Objekt direkt als Datenelement einzubauen? Wenn Du mehr von dem erklärst, was da eigentlich bei rauskommen soll, kann man dir wahrscheinlich gute Tipps geben, wie man das Problem effektiv in C++ löst.
maugli schrieb:
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?
Wie gesagt, Du willst das Problem an einer falschen Stelle lösen.
maugli schrieb:
Oder gibt es eine andere Möglichkeit wie man elegant alles, was in der Structuredefinition steht, zu kopieren?
Ja, überlass das Kopieren am besten dem Compiler.
In was für einer Beziehung stehen denn die zwei Klassen, bzw die zwei Objekte?
-
Danke
Dann frage ich mal los:
Michael E. schrieb:
Außerdem hast du pumuckls Initialisierungsliste in den Kopierkonstruktor reingezogen, was du nicht machen solltest.
Okay, warum sollte man das nicht machen? Funktioniert das so nicht, oder gibts andere Gründe?
Verständnisfrage zum Code von Gugelmoser: Öffentliche Vererbung: Das bedeutet doch, daß die vererbten Member und Funktionen in Klasse_neu von außen zugänglich sind? Das wäre bei meinem Beispiel ja erforderlich, denn es soll ja auf Member der Klasse_alt von außen "durch" Klasse_neu zugegriffen werden. Wie gesagt, eigentlich gehts um eine structure, und damit es es dann ja eh public.
Nochmal Frage zum Code von Gugelmoser: Wäre es auch möglich e in Klasse_alt zu belassen?
krümelkacker schrieb:
Spricht etwas dagegen, statt des Zeigers das Objekt direkt als Datenelement einzubauen?
Eigentlich nicht, und ich weiß das jetzt auch Nichts desto trotz interessiert es mich nun dennoch, wie man eine solche Kopie in einem Kopierkonstruktor herstellen kann.
Genaugenommen genügt es bei meiner Anwendung vielleicht sogar, allen Objekten der Klasse A genau *ein* Objekt der Klasse B bereitzustellen. In diesem Falle würde ich im Konstruktor von A den Pointer auf B übergeben. Aber das überlege ich mir noch
Ich kann gut nachvollziehen, daß es eingefleischten Programmierern Unbehagen verursacht, wenn jemand "komische" Sachen versucht, die man besser und eleganter machen kann. Aber letztlich ist das doch alles ein Lernprozess, bei dem eben auch noch anderweitig Groschen fallen, die man viell. später mal brauchen kann.
-
maugli schrieb:
Okay, warum sollte man das nicht machen? Funktioniert das so nicht, oder gibts andere Gründe?
Einen Konstruktor der Basisklasse kannst du NUR über die Initialisierungsliste aufrufen.
maugli schrieb:
Öffentliche Vererbung: Das bedeutet doch, daß die vererbten Member und Funktionen in Klasse_neu von außen zugänglich sind? Das wäre bei meinem Beispiel ja erforderlich, denn es soll ja auf Member der Klasse_alt von außen "durch" Klasse_neu zugegriffen werden.
Du willst in der Klasse Klasse_neu auf die Member von Klasse_alt zugreifen? Das hat dann nichts mit der Art der Vererbung zu tun, sondern die Member in Klasse_alt müssen dann min. protected sein. Die Art der Vererbung bestimmt die Beziehung zwischen den Klassen. Ich habe private-Vererbung genommen, weil ich es nicht als "is-a"-Beziehung ansehe.
maugli schrieb:
Nochmal Frage zum Code von Gugelmoser: Wäre es auch möglich e in Klasse_alt zu belassen?
Hä, dann hast du ja wieder alles in derselben Klasse und musst wieder jede Variable beim Kopieren auflisten.
-
Gugelmoser schrieb:
Du willst in der Klasse Klasse_neu auf die Member von Klasse_alt zugreifen? Das hat dann nichts mit der Art der Vererbung zu tun, sondern die Member in Klasse_alt müssen dann min. protected sein. Die Art der Vererbung bestimmt die Beziehung zwischen den Klassen. Ich habe private-Vererbung genommen, weil ich es nicht als "is-a"-Beziehung ansehe.
Da er auch von außerhalb auf die Member zugreifen möchte, müssen sie sogar public sein. Man sollte sowieso nie Member protected machen.
Natürlich bestimmt die Vererbungsart die Sichtbarkeit in der abgeleiteten Klasse. Hier funktioniert nur öffentliche Vererbung.
-
Michael E. schrieb:
Man sollte sowieso nie Member protected machen.
Wieso?
Michael E. schrieb:
Natürlich bestimmt die Vererbungsart die Sichtbarkeit in der abgeleiteten Klasse. Hier funktioniert nur öffentliche Vererbung.
Ich dachte mir außerhalb bezieht er sich nur auf die Subklasse.