Maison >développement back-end >C++ >Comment downcast en toute sécurité un `unique_ptr` en `unique_ptr` en C ?

Comment downcast en toute sécurité un `unique_ptr` en `unique_ptr` en C ?

Barbara Streisand
Barbara Streisandoriginal
2024-11-19 20:37:03747parcourir

How to Safely Downcast a `unique_ptr` to `unique_ptr` in C  ?

Downcasting unique_ptr to unique_ptr

Dans le domaine de la programmation orientée objet, l'héritage joue un rôle central en favorisant la réutilisation et l'extensibilité du code. Cependant, des situations peuvent survenir dans lesquelles il est nécessaire de "downcaster" un unique_ptr objet à un objet unique_ptr objet, potentiellement avec une fonction de suppression différente.

Pour relever ce défi, considérons un scénario hypothétique dans lequel une application emploie plusieurs usines, chacune produisant un unique_ptr cas. Ces fabriques peuvent offrir en interne un accès à divers types dérivés, tels que unique_ptr, unique_ptr ou unique_ptr. Pour illustrer :

unique_ptr<Base> DerivedAFactory() {
    return unique_ptr<Base>(new DerivedA);
}

L'objectif est de convertir le pointeur dans le unique_ptr à un type dérivé, même s'il diffère du type interne d'origine. On peut imaginer ce processus en pseudocode :

unique_ptr<Derived> ptr = static_cast<unique_ptr<Derived>>(DerivedAFactory());

Cependant, cette approche présente des pièges potentiels. Une solution plus robuste consiste à libérer l'objet de unique_ptr, à convertir le pointeur brut vers le type dérivé souhaité et à le réaffecter à un nouveau unique_ptr avec un suppresseur approprié.

unique_ptr<Derived> CastToDerived(Base* obj) {
    return unique_ptr<Derived>(static_cast<Derived*>(obj));
}

Ce processus de conversion devrait rester valable tant que l'objet est chargé dynamiquement à partir d'une DLL et libéré du même contexte. Cependant, lors du transfert de propriété dans différents contextes, il faut veiller à fournir un suppresseur correct à côté du pointeur.

Pour plus de sécurité et de flexibilité, il est recommandé d'utiliser des modèles de fonction pour la diffusion :

template<typename Derived, typename Base, typename Del>
std::unique_ptr<Derived, Del> 
static_unique_ptr_cast( std::unique_ptr<Base, Del>&& p )
{
    auto d = static_cast<Derived *>(p.release());
    return std::unique_ptr<Derived, Del>(d, std::move(p.get_deleter()));
}

template<typename Derived, typename Base, typename Del>
std::unique_ptr<Derived, Del> 
dynamic_unique_ptr_cast( std::unique_ptr<Base, Del>&& p )
{
    if(Derived *result = dynamic_cast<Derived *>(p.get())) {
        p.release();
        return std::unique_ptr<Derived, Del>(result, std::move(p.get_deleter()));
    }
    return std::unique_ptr<Derived, Del>(nullptr, p.get_deleter());
}

Ces modèles garantissent que le unique_ptr transmis n'est pas involontairement volé à l'appelant tout en fournissant des options de diffusion statique et dynamique. La version statique peut être utilisée lorsque le pointeur est connu pour être un Derived * sans conversion dynamique, tandis que la version dynamique effectue une vérification d'exécution à l'aide de Dynamic_cast.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn