Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Конструктор копирования при наследовании


Автор: Brain89 15.11.2011, 17:22
Здравствуйте. Хочу прояснить кое-что. Имеется достаточно простая иерархия классов
Код

class Base
{
     public:
          Base(){}
          Base(char* arg1, int arg2){}
          Base(const Base &object){}
          virtual ~Base(){}

          Base& operator=(const Base &object){}

          virtual void Method1() = 0;
          void Method2(){};

     private:
          int size;
          char* data;
};

class Derived: public Base
{
     public:
          Derived(): Base(){}
          Derived(char * arg1, int arg2, char *arg3, int arg4): Base(arg3, arg4){}
          Derived(const Derived& object){ ??? }
          ~Derived(){}

          Derived& operator=(const Derived &object){}

          virtual void Method1(){}

     private:
          int size;
          char* data;
};


Собственно, вопрос следующий. Как правильно реализовать конструктор копирования класса-потомка, чтобы внутренний объект класса-родителя также был корректно скопирован?
Есть два варианта, которые я сам могу предложить:
1. 
Код

Derived(const Derived& object): Base((Base &) object)
{
     /* Копирование данных в объект класса-потомка*/
}

2. 
Код

Derived(const Derived& object)
{
     *((Base *)this) = *((Base *) &object);
     /* Копирование данных в объект класса-потомка*/
}


Есть ли из них верный? Если оба, какой работает "правильней" ("быстрей")? Если нет, то как правильно вести себя в такой ситуации?

Автор: bsa 15.11.2011, 17:54
Brain89,  правильнее это делать так:
Код
class D : public B
{
   D(const D &other) : B(other) {...}
};
Но, существует вероятность "срезки" - если ты сделаешь класс D2 потомок D, а потом скопируешь в объект D, то скопируются только общие данные.
Обычно, полиморфные классы не допускают подобного копирования. Если нужно копирование, то делать необходимо через соответствующий виртуальный метод и new:
Код
class B
{
public:
   virtual ~B(){} //виртуальный деструктор должен быть во всех классах, предполагающих наследование
   virtual B* copy() const = 0;
protected:
   B(const B &other) {...}
};

class D : public B
{
public:
    virtual D* copy() const { D *ret = new D(*this); ... return ret; }
protected:
   D(const D &other) : B(other) {...}
};
...
B *x = y->copy();
...
delete x;

Автор: Brain89 15.11.2011, 18:27
А если у меня возникнет необходимость передать объект класса D  в функцию:

Код

void Function(D objectD);


Если конструктор копирования скрыт, такая ситуация обработается неверно. Что делать здесь?

Автор: bsa 15.11.2011, 20:34
Цитата(Brain89 @  15.11.2011,  19:27 Найти цитируемый пост)
 Что делать здесь?

использовать константные ссылки. И вообще, без крайней необходимости по значению следует передавать только стандартные типы.

Автор: Brain89 16.11.2011, 09:08
bsa,  спасибо за разъяснения. Разобрался.

Автор: cupper 28.11.2011, 11:11
Цитата(bsa @ 15.11.2011,  17:54)
Brain89,  правильнее это делать так:
Код
class D : public B
{
   D(const D &other) : B(other) {...}
};
Но, существует вероятность "срезки" - если ты сделаешь класс D2 потомок D, а потом скопируешь в объект D, то скопируются только общие данные.
Обычно, полиморфные классы не допускают подобного копирования. Если нужно копирование, то делать необходимо через соответствующий виртуальный метод и new:
Код
class B
{
public:
   virtual ~B(){} //виртуальный деструктор должен быть во всех классах, предполагающих наследование
   virtual B* copy() const = 0;
protected:
   B(const B &other) {...}
};

class D : public B
{
public:
    virtual D* copy() const { D *ret = new D(*this); ... return ret; }
protected:
   D(const D &other) : B(other) {...}
};
...
B *x = y->copy();
...
delete x;

а можно пример, а то я не совсем понял при какой варианте срезка произойдет.

Код

class B{};
class D: public B{};
class D2: public D{};

D d;
D2 d2;
d = d2; // Тут как не крути всегда будет срезка.

D* d;
D2* d2;
d = d2; // тут и копирования не будет



или же ваш вариант и нацелен на то что бы явно запретить вызов конструктора копирование по умолчанию.

Автор: bsa 28.11.2011, 15:00
Цитата(cupper @  28.11.2011,  12:11 Найти цитируемый пост)
или же ваш вариант и нацелен на то что бы явно запретить вызов конструктора копирование по умолчанию. 
именно!

Автор: scalosale 8.2.2023, 17:54
Модератор: Сообщение скрыто.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)