12
votes

C ++ dynamic_cast - Exigence polymorphe et Downcasting

Dans le code suivant, tout en construisant obj dans le cas 1, nous construisons également un objet de classe dérivé , mais ses fonctions membres sont simplement inaccessibles à obj < / code>. Donc, alors que dans le cas de la rédaction (c'est-à-dire dans le cas 2), en utilisant obj comme source, nous avons le dérivé dans celui-ci déjà. Pourquoi OBJ doit-il être polymorphique?

Si je vous ai confondu avec ma description ci-dessus, pourquoi ne obj doit-il être polymorphique lors de la mise au rebut, mais en le désactivant est-ce que doit être polymorphique tout en utilisant dynamic_cast ? xxx


0 commentaires

4 Réponses :


6
votes

à partir de 5.2.7 / 1 [expr.dynamic.cast]:

Le résultat de l'expression dynamic_cast (v) est le résultat de la conversion de l'expression v en tapez T.

[...]

si T est "pointeur sur cv1 b" et v de type "pointeur sur cv2 d" tel que B est une classe de base de D, le résultat est un pointeur sur le sous-objet B unique de l'objet D pointé vers par v.

[...]

sinon , v doit être un pointeur sur ou un lvalue d'un type polymorphe.

La norme fournit même l'exemple suivant illustrant que l'exigence de type polymorphe ne signifie pas dérivée à la conversion de base: xxx


0 commentaires

22
votes

Pour que dynamic_cast fonctionne, l'objet doit être polymorphe. La raison en est que dynamic_cast a besoin de quelque part pour stocker les informations de type qui utilisera pour effectuer la distribution, et cela en stocke les informations à côté de la machine à suivre pour la classe. Pour qu'il y ait un circuit équitable, vous devez faire au moins une de vos méthodes virtuelles.

Le moyen le plus simple autour de cela consiste à signaler le destructeur de la classe de base comme virtuel.

Upcasting (c'est-à-dire dérivé à la base) n'a pas besoin d'une distribution car le compilateur est capable de vérifier que la distribution fonctionnerait au moment de la compilation. Cependant, la même chose n'est pas vraie lorsque la sous-cuve.


1 commentaires

Vous pouvez souscrire avec static_cast dans cet exemple. Vous savez à la compilation que obj contient la bonne classe. L'utilisation de dynamic_cast est lorsque vous ne connaissez pas au moment de la compilation si l'objet est dérivé d'un autre. Par exemple, lorsque vous obtenez un pointeur hors d'une fonction et devez vérifier si l'objet renvoyé appartient à une certaine classe. (Mais vous avez raison, ils doivent être virtuels.)



0
votes

dynamic_cast

  • il est utilisé pour lancer un pointeur de base dans un pointeur dérivé. Si la base le pointeur ne pointe pas vers un objet de Le type de dérivé, il retourne
  • il est utilisé pour lancer une référence de base dans une référence dérivée. Si la référence ne pointe pas à un objet du dérivé, il jette STD :: Bad_cast.
  • Il peut être considéré comme le casting vérifié équivalent à static_cast, en ce qu'il vérifie si l'objet pointé vers est vraiment du type dérivé.

    Vous devez en savoir plus sur dynamic_cast (avec exemple) Il .


0 commentaires

0
votes
class car
{
    public:
    virtual void drive()
    {
         std::cout <<"car"<<std::endl;
    }
};
class toyota: public car
{
    public:
    virtual void drive()
    {
        std::cout <<"toyota"<<std::endl;
    }
};

class honda: public car
{
    public:
        virtual void drive()
    {
        std::cout <<"honda"<<std::endl;
    }
};

template <typename Tderived>
Tderived* dynamicCast(void* pBase)
{
    //compare the vptr of the class pointed by pBase with a temporary Tderived class. 
    //If vptr of pBase and vptr of Tderived() are pointing to the same vtable 
    //then it can be safely deduced that pBase is indeed pointing to an instance of Tderived
    if (*(int**)pBase == *(int**)&Tderived())
    {
        return (Tderived*)pBase;
    }
    else
    {
        return nullptr;
    }
}


int main()
{
    car* pCar;
    honda hondaCar;
    toyota toyotaCar;

    pCar = &toyotaCar;

    honda* pHonda = dynamicCast<honda>(pCar);
    if (nullptr != pHonda)
    {
        pHonda->drive();
    }
    else
    {
        toyota* pToyota = dynamicCast<toyota>(pCar);
        if (nullptr != pToyota)
        {
            pToyota->drive();
        }
    }
}

0 commentaires