Это правильный дизайн для ситуации?
Нет, обычно нет.Более идиоматический подход состоит в том, чтобы прекратить вручную управлять памятью, такой как 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, а не оператор присваивания.В чем разница?
Если вы хотите скопировать конструкцию, используйте конструктор копирования, а не присваивание.Используйте правильную функцию для работы.