Quelle conversion est la meilleure et quelle est la différence?
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;
}
Comme dans d'autres cas d'utilisation de shared_ptr
, vous devriez préférer utiliser make_shared
au lieu de construire le shared_ptr
manuellement:
std::shared_ptr<Base> ptr2 = std::make_shared<Derived>();
Ceci est essentiellement votre version 2, plus les divers avantages de make_shared
.
La version 1 effectue un tas de choses inutiles: vous commencez par construire un shared_ptr<Derived>
temporaire, puis vous dynamic_cast
son contenu en un pointeur de classe de base (alors qu'un static_cast
serait suffisant ici), puis vous le stockez dans un shared_ptr<Base>
différent. Vous avez donc beaucoup d'opérations d'exécution inutiles, mais aucun avantage en termes de sécurité de type par rapport à la version 2.
La seconde aurait plus de sens, car il s’agit de la transposition exacte de ce qui serait fait avec un pointeur réel tout en évitant l’utilisation d’une conversion explicite, c.-à-d.
Base* ptr = new Derived();
Une autre option serait d’utiliser std::make_shared
spécifiant Derived
comme paramètre de modèle, c’est-à-dire:
std::shared_ptr<Base> ptr2 = std::make_shared<Derived>();
Il semble que la réponse la plus évidente n’ait pas été mentionnée, donc je vais l’ajouter par souci d’exhaustivité.
Vous n'avez pas besoin d'un casting, le meilleur moyen d'y parvenir est le suivant:
#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;
}
dériver de enable_shared_from_this
ne change rien dans ce cas. vous pouvez aussi utiliser les classes suivantes (rendant votre code légèrement plus lisible)
class Base
{};
class Derived: public Base
{};
Bien sûr, je ne connais pas vos détails d'implémentation, il est donc très possible que vous ayez encore besoin de dériver de enable_shared_from_this