Как мне скопировать экземпляр класса с вложенным классом, содержащим член-указатель, во внешний класс?

Начинающий программист C ++ здесь. Допустим, у меня есть класс Outer с вложенным классом Inner. Inner содержит указатель члена, установленный во время построения, к Outer. Outer содержит функцию AddNewInner (), которая создает новый Inner, указывающий на себя, и добавляет его в вектор.

class Outer {

public:

class Inner {
public:
Inner(Outer* outerParent) : mOuterParent(outerParent) {}
Outer* mOuterParent;
}

void AddNewInner() {
Inner newInner(this);
mInnersVec.push_back(newInner);
}

vector<Inner> mInnersVec;
}

Это прекрасно работает при создании нового экземпляра Outer и вызове AddNewInner () для добавления Inners к вектору. Однако, я столкнулся с проблемой, когда я пытаюсь создать копию экземпляра Outer: вектор Inners внешней копии не указывает на копию (саму), они все еще указывают на исходный Outer.

Outer outerA;
outerA.AddNewInner();
Outer* ptrA = outerA.mInnersVec[0].mOuterParent; // this points to outerA, good!

Outer outerB = outerA;
Outer* ptrB = outerB.mInnersVec[0].mOuterParent; // this still points to outerA, bad!

Мне нужен вектор Inners в копии, чтобы указать на копию, а не на оригинал. Каков наилучший способ сделать это, или, возможно, есть альтернативный способ сделать то же самое?

0

Решение

Правильно, это ожидаемое поведение. Когда вы создаете копию объекта в C ++, компилятор использует конструктор копирования. Если вы не написали свой собственный конструктор копирования для класса, тогда он использует созданный компилятором конструктор копирования, который просто запускает (возможно, сгенерированный) конструктор копирования для каждого члена по очереди.

Так при копировании Outerпоследовательность событий выглядит так:

  • Компилятор запускает (сгенерированный) конструктор копирования для Outer
  • Это запускает конструктор копирования для std::vector, Этот конструктор назначает хранилище для нового вектора, а затем по очереди запускает конструктор копирования для каждого элемента.
  • Таким образом, (сгенерированный) конструктор копирования для Inner работает для каждого элемента, который просто копирует указатель члена (по-прежнему указывая на оригинал Outer).

Для того, чтобы обновить Inner элементы при копировании Outer, вам нужно написать собственный конструктор копирования для Outer который обновляет указатели, как вы хотите. Примерно так:

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

Обратите внимание, что всякий раз, когда вы пишете собственный конструктор копирования, вам почти всегда нужно также писать собственный оператор присваивания. Я бы порекомендовал прочитать о копировании и назначении в вашем любимом учебнике по C ++ :-).

0

Другие решения

Вам нужно использовать пользовательский конструктор копирования / оператор присваивания для вашего класса. Это позволит вам сделать глубокую копию вашего Outer* mOuterParent переменная; возможно создание нового.

Когда вы копируете указатель, вы копируете переменную, которая указывает на конкретное адресное пространство в памяти. Копирование указателя дает вам возможность получить доступ к одной и той же «истинной переменной» через две «переменные доступа».

В вашем примере Outer* mOuterParent переменная конкретного outer объект будет всегда указывают на то же самое создание outer класс указывает на этот указатель независимо от того, сколько копий этого конкретного объекта вы делаете.

0

По вопросам рекламы [email protected]