Для глубокого копирования полиморфных классов предпочитайте виртуальную функцию `clone` вместо открытого копирования/присваивания конструктора
Причина
Копирование полиморфного класса обычно не рекомендуется из-за проблемы нарезания, см. C.67. Если вам действительно нужна семантика копирования, копируйте глубоко: Предоставьте виртуальную функцию clone, которая скопирует фактический самый производный тип и вернет указатель на новый объект с владением, а затем в производных классах вернет производный тип (используйте ковариантный тип возврата).
Пример
class B {
public:
B() = default;
virtual ~B() = default;
virtual gsl::owner<B*> clone() const = 0;
protected:
B(const B&) = default;
B& operator=(const B&) = default;
B(B&&) noexcept = default;
B& operator=(B&&) noexcept = default;
// ...
};
class D : public B {
public:
gsl::owner<D*> clone() const override
{
return new D{*this};
};
};
Обычно рекомендуется использовать умные указатели для представления владения (см. R.20). Однако из-за правил языка ковариантный тип возврата не может быть умным указателем: D::clone не может вернуть unique_ptr<D>, в то время как B::clone возвращает unique_ptr<B>. Поэтому вам либо нужно последовательно возвращать unique_ptr<B> во всех переопределениях, либо использовать служебную программу owner<> из Библиотеки поддержки рекомендаций.