Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Конструктор копирования при наследовании, Как правильно реализовать копирование 
V
    Опции темы
Brain89
Дата 15.11.2011, 17:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 18.1.2010

Репутация: нет
Всего: 2



Здравствуйте. Хочу прояснить кое-что. Имеется достаточно простая иерархия классов
Код

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);
     /* Копирование данных в объект класса-потомка*/
}


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

Это сообщение отредактировал(а) Brain89 - 15.11.2011, 18:11
PM   Вверх
bsa
Дата 15.11.2011, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



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;


Это сообщение отредактировал(а) bsa - 15.11.2011, 17:55
PM   Вверх
Brain89
Дата 15.11.2011, 18:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 18.1.2010

Репутация: нет
Всего: 2



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

Код

void Function(D objectD);


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

Это сообщение отредактировал(а) Brain89 - 15.11.2011, 18:29
PM   Вверх
bsa
Дата 15.11.2011, 20:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



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

использовать константные ссылки. И вообще, без крайней необходимости по значению следует передавать только стандартные типы.
PM   Вверх
Brain89
Дата 16.11.2011, 09:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 18.1.2010

Репутация: нет
Всего: 2



bsa,  спасибо за разъяснения. Разобрался.
PM   Вверх
cupper
Дата 28.11.2011, 11:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Цитата(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; // тут и копирования не будет



или же ваш вариант и нацелен на то что бы явно запретить вызов конструктора копирование по умолчанию.
PM MAIL   Вверх
bsa
Дата 28.11.2011, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(cupper @  28.11.2011,  12:11 Найти цитируемый пост)
или же ваш вариант и нацелен на то что бы явно запретить вызов конструктора копирование по умолчанию. 
именно!
PM   Вверх
scalosale
Дата 8.2.2023, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 8.2.2023

Репутация: нет
Всего: нет




Модератор: Сообщение скрыто.

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1475 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.