Std:: shared_ptr повышение до базового класса - лучший метод?
Какое преобразование лучше, и в чем разница?
class Base
{};
class Derived : public Base, public std::enable_shared_from_this<Derived>
{};
int main(int argc, const char * argv[])
{
std::shared_ptr<Base> ptr1 = std::dynamic_pointer_cast<Base>(std::shared_ptr<Derived>(new Derived())); // version 1
std::shared_ptr<Base> ptr2 = std::shared_ptr<Derived>(new Derived()); // version 2
return 0;
}
Ответы
Ответ 1
Как и в других случаях использования shared_ptr
, вы должны использовать make_shared
вместо создания shared_ptr
вручную:
std::shared_ptr<Base> ptr2 = std::make_shared<Derived>();
Это по существу ваша версия 2, плюс различные преимущества make_shared
.
В версии 1 есть куча ненужных вещей: сначала вы создаете временный shared_ptr<Derived>
, а затем dynamic_cast
его содержимое указателю базового класса (в то время как static_cast
здесь будет достаточно), а затем вы сохраняете этот указатель в другом shared_ptr<Base>
. Таким образом, у вас много ненужных операций времени выполнения, но нет преимуществ в отношении безопасности типов по сравнению с версией 2.
Ответ 2
Второй имеет смысл, поскольку он является точным транспозированием того, что было бы сделано с помощью реального указателя, избегая при этом использования явного приведения, т.е.
Base* ptr = new Derived();
Другим вариантом будет использование std::make_shared
с указанием Derived
в качестве параметра шаблона, то есть:
std::shared_ptr<Base> ptr2 = std::make_shared<Derived>();
Ответ 3
Кажется, что самый очевидный ответ не был упомянут, поэтому я добавлю это для полноты.
Вам не нужен листинг, лучший способ выполнить это:
#include <memory>
class Base
{};
class Derived : public Base, public std::enable_shared_from_this<Derived>
{};
int main(int argc, const char * argv[])
{
std::shared_ptr<Derived> ptr1 = std::make_shared<Derived>();
std::shared_ptr<Base> ptr2 = ptr1; // no CAST NEEDED HERE AS YOU SEE :)
return 0;
}
вытекающий из enable_shared_from_this
, ничего не меняет в этом случае. вы могли бы также использовать следующие классы (делая ваш код немного читабельнее)
class Base
{};
class Derived: public Base
{};
Конечно, я не знаю ваших деталей реализации, поэтому очень возможно, что вам все еще нужно получить от enable_shared_from_this