Копировать конструктор и композицию - PullRequest
2 голосов
/ 07 января 2012

У меня есть отношения композиции между классом A и B,

class A
{
    A(); //default constructor  //EDIT
    A(const A &mA); // copy constructor //EDIT
    virtual ~A();
};


class B
{
B(A *pA); //constructor
B(const B &mB) //copy constructor
virtual ~B(); //EDIT: destructor to eliminate mA and to build the composition
A* mA;
};

Могу ли я написать конструктор копирования следующим образом:

B(const B &mB, A *pA)

Мне нужно, чтобы поддерживатькомпозиция также между копируемыми объектами.Это неправильно?Существует ли лучшее решение?Спасибо

РЕДАКТИРОВАТЬ: Я постараюсь объяснить мне лучше.Я хочу копию объекта mB и объекта mA.Но если бы в конструкторе копирования я написал mA = mB.mA, я бы скопировал адрес в исходный объект mA.Поэтому я думаю, что мне нужна глубокая копия, а не ласточка.Моя путаница возникает из-за того, что теперь из основного я сначала копирую объект mA, а затем копирую mB.Делая это, я думаю, что мне нужно назначить скопированный объект mA с помощью внешней функции, такой как

foo(A *pA)

В противном случае я мог бы решить проблему, если бы мог сделать глубокую копию mB.Это называется глубокая копия?

PS A и B являются абстрактными классами

Ответы [ 2 ]

6 голосов
/ 07 января 2012

Нет.По определению, конструктор копирования не может иметь подпись, подобную той, которую вы описали.Вот некоторые действительные подписи для конструкторов копирования:

B(const B &);
B(B &);   // Thanks Oli!

Зачем вам это нужно?Вы можете получить доступ к члену mA внутри конструктора копирования, выполнив что-то вроде этого (возможно, я допустил некоторые синтаксические ошибки):

B::B(const B & original)
{
    mA = original.mA;
}
0 голосов
/ 07 января 2012

Вы, возможно, думаете об этом.Конструктор копирования просто должен инициализировать все элементы соответствующими значениями исходного объекта, например, так:

B(B const & rhs) : mA(rhs.mA) { }

Это просто тривиальная копия, поэтому, если в ней больше ничего нет, тогда вылучше вообще не писать конструктор копирования.

С другой стороны, если вам нужна копия deep , это может выглядеть примерно так:

B(B const & rhs) : mA(::new A(rhs.mA)) { }

Тем не менее, детали этого зависят от фактической политики владения класса B в отношении pointee mA.В зависимости от этих деталей, не забудьте написать соответствующий деструктор, если это необходимо.

Вы также должны написать соответствующий оператор присваивания вашего конструктора копирования, который делает что-то нетривиальное, например:

B & operator=(B const & rhs)
{
    if (this != &rhs)
    {
        A * tmp = ::new A(*rhs.mA);    // need try/catch in general!
        ::delete mA; // OK, no exception occurred if we got here
        mA = tmp;
    }
    return *this;
}
...