Comment faire effectuer un dynamic_cast avec un unique_ptr?
J'ai une hiérarchie de classes comme suit:
class BaseSession : public boost::enable_shared_from_this<BaseSession>
class DerivedSessionA : public BaseSession
class DerivedSessionB : public BaseSession
Au sein de la classe dérivée de fonctions, j'ai régulièrement fonctions d'appel comme ceci:
Func(boost::dynamic_pointer_cast<DerivedSessionA>(shared_from_this()));
Depuis que je travaille avec shared_ptr
pour gérer les sessions, cela fonctionnait bien. Récemment, j'ai découvert que mon utilisation de shared_ptr
n'est pas optimale pour ce cas. C'est parce que ces séances sont singleton objets de maintenir un socket par client. Si le socket est rétablie, la session de copies destinées à devenir des zombies.
Comme solution de contournement, j'ai commencé à passer shared_ptr
par référence plutôt que des copies. Cela a résolu le zombie problème.
Idéalement, j'ai senti que je devais être à l'aide de unique_ptr
pour stocker la session et ensuite passer des références à d'autres fonctions. Qui a ouvert toute une boîte de pandore.
Comment puis-je cast une classe de base unique_ptr
objet de classe dérivée unique_ptr
objet? Qu'est-ce que le unique_ptr
version de la ligne suivante?
Func(boost::dynamic_pointer_cast<DerivedSessionA>(shared_from_this()));
Je veux juste une copie de l'objet session, tout le reste doit être de référence.
Si dynamic_cast échoue, la touche Func obtient un objet nul, et il annule l'opération. Je ne veux pas bouger, le propriétaire doit rester la même.
Je pense que je suis à la recherche d'un weak pour unique objet. Court de revenir à C pointeur, est-il un autre choix?
Réponse courte: non.
unique_ptr
implique la propriété. Des pointeurs faibles exiger l'observation de la logique qui sous-entend de verrouillage et de compteurs refcount. Qui vient à un prix, qui est pourquoi vous devez utiliser des shared_ptr
si vous êtes si incliné. La bonne nouvelle est que vous pouvez utiliser std::dynamic_pointer_cast<>
avec qui trop (et weak_ptr
). Tout le monde gagne.Je suis d'accord avec sehe. La création d'un unique_ptr ce point à une ressource déjà possédé par un autre pointeur intelligent, sans déplacement de la ressource entre les deux récipients est faux. Un weak n'a pas la propriété de la ressource pointée mais une faiblesse de référence: ainsi, toute opération à partir du weak à la unique_ptr est tout simplement impossible ou fortement découragé
OriginalL'auteur Sharath | 2014-10-15
Vous devez vous connecter pour publier un commentaire.
Sauf si vous souhaitez transférer la propriété de votre
std::unique_ptr<T>
, votre fonction doit prendre pointeur ou une référence àT
.Donc la signature de
Func
doit être quelque chose commeFunc(DerivedSessionA*)
et puis, votre appel peut ressembler à:
Ou, comme tu semble l'appeler directement à partir d'une méthode dans
BaseSession
:dynamic_cast
retournenullptr
si de type dynamique, ce n'est pas vraiment unDerivedSessionA*
(ou enfant).OriginalL'auteur Jarod42
Mise à jour
La question a été clarifiée:
Dans ce cas, la solution est simple:
Fait. Il jette si le casting n'a pas réussi.
Casting
shared_ptr
Pour
shared_ptr
il eststd::dynamic_pointer_cast<>
(http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast)Casting
unique_ptr
La façon la plus simple semble:
Que l'auteur a à juste titre fait remarquer, cela peut présenter une fuite de l'objet si la conversion a échoué. C'est pas très utile.
Une raison pourquoi les
dynamic_unique_ptr_cast<>
n'existe pas peut être que leunique_ptr
type n'efface pas la deleter. Il pourrait être difficile/impossible de choisir une suppression de la cible, de type pointeur.Toutefois, pour les cas simples, vous pouvez utiliser quelque chose comme ceci:
Cela fait zéro sens. Si la propriété est partagée, l'utilisation shared_ptr ou même un pointeur brut (
dynamic_cast<B*>(p.get())
). La création d'un deux différents pointeurs intelligents pour le même objet est toujours une mauvaise conception de l'odorat et d'avoir des ennuis.unique_ptr
est précisément sur le transfert de la propriété. Si vous n'avez pas besoin, utiliser quelque chose d'autre.Merci @sehe. C'est une belle tournure à Jarad42 de la solution. 🙂
Tous les trois approches de la compilation fine sur MSVC 19: le simplist prendre, exception sûr wrapper ainsi que - évidemment - la dynamique de référence cast. Si vous avez de la difficulté à comprendre votre code C++, veuillez vous suffit de poster une question la prochaine fois?
Oui, il y a eu beaucoup de bruit venant de ce post au cours des deux derniers jours. J'ai essayé de préserver la valeur, si possible la dernière fois, mais ce débat dure depuis trop longtemps déjà et ne semble pas qu'il portera ses fruits rapidement. Prendre de chat, ou l'un de vous poser une nouvelle question sur le problème et de laisser un détachement de la 3e partie de trier la bonne réponse.
OriginalL'auteur sehe
Simplement à obtenir le pointeur stocké à l'aide de la
std::unique_ptr<>::get()
méthode:que si
shared_from_this()
a ce prototype:OriginalL'auteur Stefano Buora