Mise à jour: le shared_ptr dans cet exemple est comme celui de Boost, mais il ne prend pas en charge shared_polymorphic_downcast (ou dynamic_pointer_cast ou static_pointer_cast d'ailleurs)!
J'essaie d'initialiser un pointeur partagé sur une classe dérivée sans perdre le nombre de références:
struct Base { };
struct Derived : public Base { };
shared_ptr<Base> base(new Base());
shared_ptr<Derived> derived;
// error: invalid conversion from 'Base* const' to 'Derived*'
derived = base;
Jusqu'ici tout va bien. Je ne m'attendais pas à ce que C++ convertisse implicitement Base * en Derived *. Cependant, je veux la fonctionnalité exprimée par le code (c'est-à-dire maintenir le nombre de références tout en abaissant le pointeur de base). Ma première pensée a été de fournir un opérateur de cast dans Base afin qu'une conversion implicite en Derived puisse avoir lieu (pour les pédants: je vérifierais que le cast en bas est valide, ne vous inquiétez pas):
struct Base {
operator Derived* ();
}
// ...
Base::operator Derived* () {
return down_cast<Derived*>(this);
}
Eh bien, ça n'a pas aidé. Il semble que le compilateur ait complètement ignoré mon opérateur de transtypage. Des idées sur la façon dont je pourrais faire fonctionner l'affectation shared_ptr? Pour des points supplémentaires: quel type de type Base* const
est? const Base*
Je comprends, mais Base* const
? À quoi const
fait-il référence dans ce cas?
Vous pouvez utiliser dynamic_pointer_cast
. Il est soutenu par std::shared_ptr
.
std::shared_ptr<Base> base (new Derived());
std::shared_ptr<Derived> derived =
std::dynamic_pointer_cast<Derived> (base);
De plus, je ne recommande pas d'utiliser l'opérateur cast dans la classe de base. Un casting implicite comme celui-ci peut devenir la source de bugs et d'erreurs.
- Update: Si le type n'est pas polymorphe, std::static_pointer_cast
peut être utilisé.
Je suppose que vous utilisez boost::shared_ptr
... Je pense que vous voulez dynamic_pointer_cast
ou shared_polymorphic_downcast
.
Ceux-ci nécessitent cependant des types polymorphes.
quel type de type
Base* const
est?const Base*
Je comprends, maisBase* const
? À quoiconst
fait-il référence dans ce cas?
const Base *
est un pointeur mutable sur une constante Base
.Base const *
est un pointeur mutable sur une constante Base
.Base * const
est un pointeur constant vers un Base
mutable.Base const * const
est un pointeur constant vers une constante Base
.Voici un exemple minimal:
struct Base { virtual ~Base() { } }; // dynamic casts require polymorphic types
struct Derived : public Base { };
boost::shared_ptr<Base> base(new Base());
boost::shared_ptr<Derived> derived;
derived = boost::static_pointer_cast<Derived>(base);
derived = boost::dynamic_pointer_cast<Derived>(base);
derived = boost::shared_polymorphic_downcast<Derived>(base);
Je ne sais pas si c'était intentionnel que votre exemple crée une instance du type de base et la transforme, mais cela sert à illustrer la différence de manière intéressante.
Le static_pointer_cast
va "le faire". Cela entraînera un comportement indéfini (un Derived*
pointant sur la mémoire allouée et initialisée par Base
) et provoquera probablement un plantage, ou pire. Le nombre de références sur base
sera incrémenté.
Le dynamic_pointer_cast
donnera un pointeur nul. Le nombre de références sur base
sera inchangé.
Le shared_polymorphic_downcast
aura le même résultat qu'une conversion statique, mais déclenchera une assertion, semblant plutôt réussir et conduire à un comportement indéfini. Le nombre de références sur base
sera incrémenté.
Voir (lien mort) :
Parfois, il est un peu difficile de décider d'utiliser
static_cast
oudynamic_cast
, et vous souhaitez avoir un peu des deux mondes. Il est bien connu que dynamic_cast a un temps d'exécution, mais il est plus sûr, alors que static_cast n'a aucun temps, mais il peut échouer en silence. Comme ce serait bien si vous pouviez utilisershared_dynamic_cast
dans les versions de débogage etshared_static_cast
dans les versions. Eh bien, une telle chose est déjà disponible et s'appelleshared_polymorphic_downcast
.
Si quelqu'un arrive ici avec boost :: shared_ptr ...
C'est ainsi que vous pouvez effectuer une conversion vers le Boost shared_ptr dérivé. En supposant que Derived hérite de Base.
boost::shared_ptr<Base> bS;
bS.reset(new Derived());
boost::shared_ptr<Derived> dS = boost::dynamic_pointer_cast<Derived,Base>(bS);
std::cout << "DerivedSPtr is: " << std::boolalpha << (dS.get() != 0) << std::endl;
Assurez-vous que la classe/structure 'Base' a au moins une fonction virtuelle. Un destructeur virtuel fonctionne également.