web-dev-qa-db-fra.com

std :: shared_ptr upcasting à la classe de base - meilleure méthode?

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;
}
15
Piotr Wach

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.

16
ComicSansMS

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>();
3
JBL

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

0
GameDeveloper