2016-07-25 26 views
0

Anfänger C++ Programmierer hier. Sagen wir, ich habe eine Klasse Outer mit einer verschachtelten Klasse Inner. Inner enthält ein Zeigerelement, das während der Konstruktion festgelegt wurde, nach Outer. Outer enthält eine Funktion AddNewInner(), die ein neues Inneres erstellt, das auf sich selbst zeigt und es einem Vektor hinzufügt.Wie kopiere ich eine Instanz einer Klasse mit einer geschachtelten Klasse, die ein Zeigerelement in der äußeren Klasse enthält?

Das funktioniert gut, wenn Sie eine neue Instanz von Outer erstellen und AddNewInner() aufrufen, um dem Vektor Inneres hinzuzufügen. Ich bin jedoch auf ein Problem gestoßen, als ich versuche, eine Kopie einer Instanz von Outer zu erstellen: Der Vektor der äußeren Kopie zeigt nicht auf die Kopie (selbst), sondern auf das ursprüngliche Äußere.

Ich brauche den Vektor der Inneren in der Kopie, um auf die Kopie zu zeigen, nicht das Original. Was ist der beste Weg, dies zu erreichen, oder gibt es vielleicht einen alternativen Weg, um das Gleiche zu tun?

+0

Aah ....Sie müssen in Kopierkonstruktoren nachlesen. Google-Kopierkonstruktoren, tiefe Kopie, flache Kopie. Viele Referenzen da draußen. – cplusplusrat

Antwort

0

Korrekt, dies ist das erwartete Verhalten. Wenn Sie eine Kopie eines Objekts in C++ erstellen, verwendet der Compiler den Kopierkonstruktor. Wenn Sie keinen eigenen Kopierkonstruktor für eine Klasse geschrieben haben, wird der vom Compiler generierte Kopierkonstruktor verwendet, der wiederum den (möglicherweise generierten) Kopierkonstruktor für jedes Element ausführt. So

wenn ein Outer kopieren, geht die Abfolge der Ereignisse wie folgt aus:

  • Compiler läuft die (generiert) Copy-Konstruktor für Outer
  • Dies läuft den Kopierkonstruktor für std::vector. Dieser Konstruktor ordnet den Speicher für den neuen Vektor zu und führt dann den Kopierkonstruktor für jedes Element der Reihe nach aus.
  • Also wird der (generierte) Kopierkonstruktor für Inner für jedes Element ausgeführt, das nur den Elementzeiger kopiert (immer noch auf das Original zeigend) Outer).

Um die Inner Elemente zu aktualisieren, wenn ein Outer kopieren, müssen Sie eine benutzerdefinierte Copykonstruktor für Outer schreiben, die die Zeiger aktualisiert, wie Sie möchten. So etwas wie so:

Outer::Outer(const Outer& other) 
    : mInnersVec(other.mInnersVec) // Do initial vector copy 
{ 
    // Update vector elements 
    for (auto& elem : mInnersVec) { 
     elem.mOuterParent = this; 
    } 
} 

Beachten Sie, dass, wenn Sie eine benutzerdefinierte Copykonstruktor schreiben, Sie fast immer brauchen auch einen benutzerdefinierten Zuweisungsoperator zu schreiben. Ich empfehle Ihnen, in Ihrem bevorzugten C++ - Lehrbuch über das Kopieren und die Zuordnung zu lesen :-).

0

Sie müssen eine benutzerdefinierte copy constructor/assignment operator für Ihre Klasse verwenden. Dadurch können Sie eine tiefe Kopie Ihrer Outer* mOuterParent Variable erstellen; wahrscheinlich ein neues erstellen.

Wenn Sie einen Zeiger kopieren, kopieren Sie eine Variable, die auf einen bestimmten Adressraum im Speicher zeigt. Das Kopieren des Zeigers gibt Ihnen nur die Möglichkeit, über zwei 'Accessor-Variablen' auf dieselbe 'wahre Variable' zuzugreifen.

In Ihrem Beispiel die Outer* mOuterParent Variable eines bestimmten outer Objekt wird immer auf die gleiche Instanziierung eines outer Klasse ganz gleich von diesem Zeiger zeigt, wie viele Kopien des jeweiligen Objekts, das Sie machen.