62 votes

On ne peut pas faire de downcast parce que la classe n'est pas polymorphe ?

Est-il possible d'avoir de l'héritage sans méthodes virtuelles ? Le compilateur dit que le code suivant n'est pas polymorphe.

Ejemplo:

class A {
public:
    int a;
    int getA(){return a;};
}

class B : public A {
public:
    int b;
    int getB(){return b;};
}

Dans une autre classe, nous essayons de descendre d'une A à un objet B objet :

 A *a = ...;
 B *b = dynamic_cast<B*>(a)

mais cela donne l'erreur de compilation suivante :

 cannot dynamic_cast ... (source type is not polymorphic)

0 votes

En plus de la réponse acceptée, vous pouvez vérifier cette question : Quand faut-il utiliser static_cast, dynamic_cast et reinterpret_cast ? ( stackoverflow.com/questions/332030/ )

93voto

Dave S Points 11381

Malgré les erreurs de syntaxe, vous ne pouvez pas dynamic_cast un type non polymorphe. static_cast est le cast que vous utiliserez dans ce cas, si vous savez qu'il s'agit en fait d'un objet du type cible.

La raison en est que : static_cast permet au compilateur d'effectuer une vérification au moment de la compilation "L'entrée peut-elle être convertie en sortie ? Cela peut être utilisé dans les cas où vous effectuez un casting vers le haut ou vers le bas d'une hiérarchie d'héritage de pointeurs (ou de références). Mais la vérification n'a lieu qu'au moment de la compilation, et le compilateur suppose que vous savez ce que vous faites.

dynamic_cast ne peut être utilisé que dans le cas d'un transfert de pointeur ou de référence, et en plus de la vérification à la compilation, il effectue une vérification supplémentaire à l'exécution pour s'assurer que le transfert est légal. Elle exige que la classe en question ait au moins une méthode virtuelle, ce qui permet au compilateur (s'il prend en charge RTTI) d'effectuer cette vérification supplémentaire. Toutefois, si le type en question ne possède aucune méthode virtuelle, il ne peut pas être utilisé.

Le cas le plus simple, et probablement utile si vous faites circuler des pointeurs comme ceci, est d'envisager de rendre virtuel le destructeur de la classe de base. En plus de vous permettre d'utiliser le cast dynamique, cela permet également aux destructeurs appropriés d'être appelés lorsqu'un pointeur de la classe de base est supprimé.

38voto

Aqua Points 14652

Vous avez besoin d'au moins une méthode virtuelle dans une classe pour run-time type information (RTTI) pour appliquer avec succès l'opérateur dynamic_cast.

22voto

user993954 Points 96

Rendez simplement le destructeur virtuel (toujours le faire pour toute classe, par sécurité).

12 votes

Pas pour n'importe quelle classe mais pour la classe qui est destinée à être une classe de base

0 votes

Ne serait-il pas dangereux, car le destructeur de l'enfant serait invoqué à la place du destructeur du parent ? Un programmeur pourrait oublier d'appeler BaseClass::~BaseClass() et se retrouverait dans la merde car la partie parentale ne serait pas détruite.

1 votes

@Kari, le destructeur parent (base) est automatiquement appelé après le destructeur enfant. Il n'est pas nécessaire d'appeler explicitement ce destructeur.

6voto

Murali Krishna Points 126

Oui, le dynamic_cast pour les types non polymorphes n'est pas autorisé. La classe de base doit avoir au moins une méthode virtuelle. Ce n'est qu'alors que cette classe peut être appelée polymorphe.

Cet article explique un exemple similaire : http://www.cplusplus.com/doc/tutorial/typecasting/

4voto

tyger Points 181
A a;
B *b = dynamic_cast<B*>(a)

Ici, a est un objet et b est un pointeur.

En fait, l'upcasting et le downcasting sont tous deux autorisés en C++. Mais lorsque vous utilisez le downcasting, vous devez faire attention à deux choses :

  1. La superclasse doit avoir au moins une méthode virtuelle.
  2. Comme la superclasse est plus "petite" que la sous-classe, il faut utiliser l'objet mémoire avec précaution.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X