C ++ 11 — Скопировать конструкцию умного указателя, указывающего на абстрактный тип?

мне нравится станд :: unique_ptr. Это помогает мне предотвратить утечки памяти, что чрезвычайно полезно. Но есть одна проблема: копирование и создание не разрешены.

Несмотря на то, что это ограничение служит безопасности программиста, оно также довольно ограниченно. Если вы работаете с классами с std :: unique_ptr в качестве их членов, используя назначение копирования и конструкцию, у вас в конечном итоге возникнут проблемы. Вот почему я создал свою собственную обертку вокруг unique_ptr с копированием и назначением. Вот это конструктор копирования:

template<typename T, class Deleter>
PointerSmartSafe<T, Deleter>::PointerSmartSafe(PointerSmartSafe const& pointer_smart_safe_) noexcept : _m_opPointerUnique((_m_opPointerUnique == nullptr) ? new T(*_m_opPointerUnique.get()) : nullptr){

}

А вот оператор копирования копии:

template<typename T, class Deleter>
PointerSmartSafe<T, Deleter>& PointerSmartSafe<T, Deleter>::operator=(PointerSmartSafe const& pointer_smart_safe_) noexcept{
_m_opPointerUnique = decltype(_m_opPointerUnique)(new T(*_m_opPointerUnique.get()));
return *this;
}

Все работало нормально, пока я не использовал абстрактный базовый класс как тип (T). Я получил сообщение об ошибке, подобное следующему:

error: cannot allocate an object of abstract type 'AbstractBaseClass'

Это сбивает с толку меня. Существует ли обходной путь?

1

Решение

Но есть одна проблема: копирование и создание не разрешены.

Это не проблема. Если вы обнаружите, что это проблема, вы делаете что-то не так.

Несмотря на то, что это ограничение служит безопасности программиста, оно также довольно ограниченно.

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

Вот почему я создал свою собственную обертку вокруг unique_ptr с копированием и назначением.

То, что вы хотите, не unique_ptr затем вы хотите «клон ptr»

Это сбивает с толку меня

Что смущает в этом? Вы пытаетесь создать экземпляр абстрактного базового класса. Ваш код также нарезал бы неабстрактные базы. Это по своей сути небезопасно.

Это должно сказать вам кое-что важное: копирование объекта, удерживаемого unique_ptr не может быть сделано в общем, это требует контекста, что unique_ptr не имеет Этот контекст должен исходить либо от объекта, которому принадлежит то, что вы хотите скопировать (для этого требуется, чтобы владелец объекта знал динамический тип объекта), либо от того, что вы хотите скопировать сам (который может использовать виртуальные функции для создания копии в контекст правильного динамического типа.)

Обычное решение — добавить виртуальный clone() функция-член для ваших типов, а затем использовать это, когда это возможно.

Вы можете включить это в свой конструктор примерно так:

template<typename T>
auto clone(T* t) -> decltype(t->clone())
{ return t->clone(); }

template<typename T>
std::unique_ptr<T> clone(T* t, ...)
{ return std::unique_ptr<T>(new T(*t)); }

// ...

_m_opPointerUnique((_m_opPointerUnique == nullptr) ? clone(_m_opPointerUnique.get()) : nullptr)
6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]