Im Kopierkonstruktor auf den Standard-Kopierkonstruktor zugreifen?
-
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.
-
Gugelmoser schrieb:
Einen Konstruktor der Basisklasse kannst du NUR über die Initialisierungsliste aufrufen.
Ich verstehe. Ich habe grade mal versucht ein Objekt innerhalb einer Klasse zu instantiieren (Klasse objekt(parameter);) und das klappt auch nur über die Initialisierungsliste. Wieder was gelernt
Gugelmoser schrieb:
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.
Naja, könnte ich dann nicht den Kopierkonstruktor der abgeleiteten Klasse schreiben und darin auf den (Standard-)Kopierkonstruktor der Basisklasse zugreifen? Dann könnte man erstmal alles kopieren, und dann die Pointer-Objekte duplizieren. Oder nicht? (wie gesagt: Das mit den Erbschaften hab ich noch nicht so ganz durchschaut)
@alle: Für mein Problem hab ich jetzt eine relativ einfache Methode gefunden, ohne im Programm alles umwerfen zu müssen. Das ist zwar elegant, funktioniert aber.
class klasse_B {//... }; class klasse_A { klasse_B * alter_b_pointer; klasse_B B_objekt_innerhalb_A_objekt; klasse_A::klasse_A() {alter_b_pointer=&B_objekt_innerhalb_A_objekt; } void klasse_A::allocate(void) {alter_b_pointer=&B_objekt_innerhalb_A_objekt; //... } };
Die Funktion "allocate()" war insofern kein Problem, da es das intern sowieso schon gab.
Vielleicht beschreibe ich doch noch kurz die Anwendung, damit die Fragestellungen hier nicht so trocken rüberkommt: Klasse B ist bei mir eine Serialisierungsklasse, die ich mir selbst geschrieben habe. allocate() wird vor dem Zugriff auf den b_pointer von außen sowieso aufgerufen (in der Funktion allocate werden die Variablen der klasse_A der Serialisierungsklasse bekannt gemacht: Klasse B bekommt dabei Pointer auf jedes Datenobjekt, Datentyp und Variablennamen (und weitere Infos) und speichert das alles in Klasse_B in Maps.)
Über Klasse B kann man nun per Variablennamen (als string) auf die Objekte der Klasse_A zugreifen. Ausserdem macht Klasse B Serialisierungen in/aus Textfiles in einem menschen-lesbaren Format und kann z.B. auch Changelogs innerhalb von Klasse A erzeugen und verwalten.
Für solche Aufgaben gibt es vermutlich Bibliotheken, aber ich wollte das gerne selbst machen, und es funktioniert ja auch. Nur hatte ich deswegen bis vorhin ein Mega-Datenleck, das jetzt aber gestopft ist
-
maugli schrieb:
Ich habe grade mal versucht ein Objekt innerhalb einer Klasse zu instantiieren (Klasse objekt(parameter);) und das klappt auch nur über die Initialisierungsliste. Wieder was gelernt
Wie meinst du das genau. Hast du kurz ein Beispielcode?
maugli schrieb:
Naja, könnte ich dann nicht den Kopierkonstruktor der abgeleiteten Klasse schreiben und darin auf den (Standard-)Kopierkonstruktor der Basisklasse zugreifen? Dann könnte man erstmal alles kopieren, und dann die Pointer-Objekte duplizieren.
Doch, du kannst im Copy-Konstruktor der abgeleiteten Klasse den Default-Konstruktor der Basisklasse aufrufen, aber ein Default-Konstruktor macht, wie der Name es schon sagt, keine Kopien. Oder verstehe ich dich falsch? Kannst ja auch eben ein Codebeispiel machen, wie du das meinst.
-
Gugelmoser schrieb:
maugli schrieb:
...und das klappt auch nur über die Initialisierungsliste...
Wie meinst du das genau. Hast du kurz ein Beispielcode?
Naja, wenn ich eine Klasse habe, deren Konstruktor einen Parameter bekommt, also so:
class B {int var; B(int rein) {var=rein; } };
Und nun möchte ich ein B-Objekt in der A-Klasse instantiieren.
class A {B b_objekt; // dann kann ich hier offenbar den Parameter für den Konstruktor von B nicht übergeben A() : b_objekt(5) // hier aber schon { } };
Gugelmoser schrieb:
Doch, du kannst im Copy-Konstruktor der abgeleiteten Klasse den Default-Konstruktor der Basisklasse aufrufen, aber ein Default-Konstruktor macht, wie der Name es schon sagt, keine Kopien. Oder verstehe ich dich falsch? Kannst ja auch eben ein Codebeispiel machen, wie du das meinst.
Sorry, das hab ich falsch beschrieben. Was ich meinte war: Wenn man in der abgeleiteten Klasse Konstruktor, Destruktor, Copykonstruktor und =operator selbst schreibt, müsste man doch in diesen Funktionen jeweils auf Konstruktor, Destruktor, Copykonstruktor und =operator der Basisklasse zugreifen können. Dann könnte man diese für "flache" Kopie nutzen, und alles, was mit den Pointern zu tun hat, selbst schreiben.
Vielleicht doch noch eine Verständnisfrage zur Erbschaft: Funktionen einer abgeleiteten Klasse können doch auf Member der Basisklasse zugreifen?
-
maugli schrieb:
class A {B b_objekt; // dann kann ich hier offenbar den Parameter für den Konstruktor von B nicht übergeben A() : b_objekt(5) // hier aber schon { } };
Richtig, oder auch so möglich:
class A {B b_objekt; A() { b_objekt = 5; // Mach das aber nicht. Nimm stets die Initialisierungsliste. } };
maugli schrieb:
Wenn man in der abgeleiteten Klasse Konstruktor, Destruktor, Copykonstruktor und =operator selbst schreibt, müsste man doch in diesen Funktionen jeweils auf Konstruktor, Destruktor, Copykonstruktor und =operator der Basisklasse zugreifen können.
Kann man auch. (Außer sie sind in der Basisklasse private deklariert)
maugli schrieb:
Dann könnte man diese für "flache" Kopie nutzen, und alles, was mit den Pointern zu tun hat, selbst schreiben.
Richtig. Das haben wir ja gemacht in meinem Beispielcode. Da haben wir doch auf den Copy-Konstruktor und operator= der Basisklasse zugegriffen, und nur für den Pointer haben wir selber etwas geschrieben.
maugli schrieb:
Vielleicht doch noch eine Verständnisfrage zur Erbschaft: Funktionen einer abgeleiteten Klasse können doch auf Member der Basisklasse zugreifen?
Ja, wenn die Member der Baisklasse protected oder public sind.
-
Gugelmoser schrieb:
Richtig, oder auch so möglich:
class A {B b_objekt; A() { b_objekt = 5; // Mach das aber nicht. Nimm stets die Initialisierungsliste. } };
Okay. Aber zum Verständnis: Warum ruft ein = an dieser Stelle den Konstruktor von B auf?
Und: Ginge das auch mit mehreren Parametern?Gugelmoser schrieb:
maugli schrieb:
Dann könnte man diese für "flache" Kopie nutzen, und alles, was mit den Pointern zu tun hat, selbst schreiben.
Richtig. Das haben wir ja gemacht in meinem Beispielcode. Da haben wir doch auf den Copy-Konstruktor und operator= der Basisklasse zugegriffen, und nur für den Pointer haben wir selber etwas geschrieben.
Genau, in Deinem Beispiel ist der Pointer nur nicht in der Basisklasse. Wäre er das, würde der Copy-Konstruktor der Basisklasse den Pointer zwar flach kopieren, und ich könnte ihn dann durch die Adresse eines neuen, identischen Objekts überschreiben.
Danke Dir (und allen anderen!), ich glaube ich blicke die Mechanik dieser Lösung jetzt