Использовать базовый класс Copy CTOR в производном классе - PullRequest
0 голосов
/ 30 мая 2018

Я знаю, что на эту тему есть много постов, но я не смог найти ни одного, чтобы полностью ответить на мои вопросы.

Скажем, у меня есть Базовый класс и Производный класс, в котором я реализовал CCtor иоператор присваивания для него, что-то вроде следующего:

class Base {
    char * name;
    ....
    Base(const Base& other) :name(nullptr) { *this = other }
    void operator=(const Base& other) { ... Deep copy of name } 
}


class Derived : public Base {
.... 
    Derived(const Derived& other) { *this = other ; }
    void operator=(const Derived& other) {
        Base::operator=(other);
        .....
    }

Теперь у меня есть несколько вопросов об этом дизайне.

  1. Это правильный дизайн для ситуации?
  2. Если у меня есть третий класс, между базовым и производным классом, но он содержит только примитивные типы, куда я должен скопироватьих?Например, использовать оператор присваивания по умолчанию второго класса?построить новый?только скопировать их на третий уровень?
  3. Я мог бы аналогично вызывать базовый класс CCtor внутри производного класса CCtor вместо оператора присваивания.Какая разница?Если я помещу их в оба метода, он попытается скопировать значения два раза?

Редактировать: Просто чтобы уточнить, дизайн - это то, что мне дали в моем проекте. У меня есть указатели, поэтому я имеюиспользовать глубокую копию.

1 Ответ

0 голосов
/ 30 мая 2018

Это правильный дизайн для ситуации?

Нет, обычно нет.Более идиоматический подход состоит в том, чтобы прекратить вручную управлять памятью, такой как char* name, и использовать std::string или другой тип, который делает правильные вещи:

Class Base {
    std::string name;
    ....
    Base(const Base& other) = default;
    Base& operator=(const Base& other) = default;
};

(Обратите внимание, что операторы присваивания должны возвращать ссылку на класс,не void).

Или инкапсулируйте управление памятью в дизайн класса специально для этой цели (но std::string уже является этим типом).

Если вы действительно действительно нужно сделать это тупым, подверженным ошибкам способом, затем реализовать свой конструктор копирования, чтобы сделать копирование:

    Base(const Base& other) { / * deep copy of name */ }

Затем реализовать назначение как копирование и обмен:

    Base& operator=(const Base& other)
    {
      Base tmp(other);
      this->swap(tmp);
      return *this;
    }

Это означает, что вам нужна дешевая, не генерирующая swap(Base&) функция-член.

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

Derived(const Derived& other) : Base(other) { }

И для назначения можно использовать базовое назначение:

Derived& operator=(const Derived& other)
{
   Base::operator=(other);
   return *this;
}

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

class Derived : public Base {
public:
    Derived(const Derived&) = default;
    Derived& operator=(const Derived& ) = default;

Если у меня есть третий класс, между базовым и производным классом, но он содержит только примитивные типы, где шоудЯ их копирую?Например, использовать оператор присваивания по умолчанию второго класса?построить новый?копировать их только на третьем уровне?

Вы должны определить конструктор копирования и оператор присваивания этого класса, используя = default.Как только вы сделали Base безопасным для копирования с правильным поведением, составление других классов для его использования становится тривиальным.Поведение по умолчанию будет делать правильные вещи.Вам нужно определять эти операции только вручную, если вам нужна специальная обработка для чего-то вроде динамически выделяемой памяти, которая неправильно управляется типом RAII.

Я мог бы аналогично вызвать базовый класс CCtor внутрипроизводный класс CCtor, а не оператор присваивания.В чем разница?

Если вы хотите скопировать конструкцию, используйте конструктор копирования, а не присваивание.Используйте правильную функцию для работы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...