8
votes

Vérification si un casting croisé pourrait éventuellement fonctionner?

Je sais que c'est légal d'utiliser dynamic_cast pour faire une "coulée croisée" sur une hiérarchie de classe. Par exemple, si j'ai des cours qui ressemblent à ceci: xxx

si j'ai un pointeur a * pointant sur un objet de type C , alors je peux utiliser xxx

pour obtenir un pointeur sur l'objet de base B du C i ' m pointant à.

La raison pour laquelle je mentionne c'est que, à l'époque que j'écris le code ci-dessus, il est possible que le compilateur n'ait pas encore vu la définition de C même si Il est vu A et b . Cela signifie qu'il est possible que le compilateur ne détecte aucun type de connexion entre A et B , mais il doit toujours compiler le code de toute façon parce qu'il est possible pour une classe comme une classe c pour exister et pour le dynamic_cast pour réussir dans certaines circonstances.

Le problème est que cela signifie que je peux accidentellement transversalement à un objet du mauvais type. Supposons que j'ai des cours qui ressemblent à ceci: xxx

ici, d est une classe aléatoire non liée. Si j'essaie d'écrire quelque chose comme ceci: xxx

alors ce dynamic_cast échouera toujours au moment de l'exécution, car il n'y a pas de moyen possible de connecter et d . Si j'utilise d accidentellement parce que je voulais utiliser B , le compilateur ne me donnera aucune indication que j'ai une fonte sans signification.

Ma question est la suivante: Y a-t-il une manière que je puisse obtenir le compilateur pour m'emperner que la distribution échouera toujours au moment de l'exécution? Je serais heureux d'une solution de niveau de langue ou d'un réglage du compilateur pour tout Compilateur majeur qui pourrait détecter cela. S'il y a un outil externe, c'est bien aussi; Je veux juste savoir s'il est possible d'attraper cette classe d'erreurs.


4 commentaires

Cela devrait être un niveau de liaison sûrement? Au moment de la compilation, vous ne savez pas qu'une classe ne peut pas être créée qui dérive de a et d ?


@ Keith - définitivement, sauf si vous avez un compilateur omniscient. Homme, j'en veux un de ceux-là ... :-)


@Keith: Même la liaison peut ne pas avoir d'informations complètes sur tous types, comme expliqué dans ma réponse.


@Ben Voigt- Absolument, je me suis produit aussi.


3 Réponses :


-3
votes

la vérité est lorsque vous utilisez dynamic_cast Vous pouvez lancer tout pointeur de type polymorphique sur n'importe quel pointeur de type polymorphe, même lorsque des classes ne sont pas liées l'une à l'autre.

Si vous souhaitez vérifier la compilation, vous devez utiliser d'autres cases - static_cast ou des conversions implicites - qui pourrait ne pas convenir à d'autres raisons dans de nombreux cas.

La solution que nous utilisons lorsque dynamic_cast est nécessaire est une fonction modélise qui fait dynamic_cast et jette une exception si un pointeur null est obtenu. C'est bien sûr un contrôle d'exécution uniquement, mais c'est plutôt fiable.


1 commentaires

-1: Vous pouvez dynamic_cast une classe polymorphe à une autre classe polymorphe uniquement si leur RTTI est liée. Sinon, vous obtenez un 0 PTR (si vous lancez sur PTR), ou si vous obtenez une exception BAD_CAST si vous lancez sur la référence non liée à la classe polymorphe.



3
votes

Il n'est pas possible de le détecter à la compilation. La classe C qui introduit la relation peut être trouvée dans une bibliothèque chargée de manière dynamique qui n'a pas encore été écrite et que le compilateur ne peut pas prouver le contraire.

Il peut y avoir quelques exceptions à exception. Si A n'a que des constructeurs privés (ou un destructeur privé), le compilateur peut être certain qu'il n'y aura pas de nouvelles sous-classes qui ne sont pas nommées d'amis par A . < / p>


2 commentaires

C'est définitivement vrai. Cependant, serait-il possible d'obtenir une manière d'une manière ou d'une autre d'une manière d'une manière ou d'une autre d'une manière d'une manière ou d'une autre, de faire en sorte que la liaison me prévienne quelque chose à l'effet de "Hey, il suffit de vous faire savoir que cela a l'air suspect?" Même si cela peut ne pas finir par être un problème?


@TemplatetypeDef: étant donné que dynamic_cast ressemble à une fonction de modèle, vous pouvez peut-être introduire un wrapper, utiliser #define dynamic_cast coché_dynamic_cast pour forcer l'utilisation de l'emballage, puis d'obtenir une manière d'une quelconque Une liste de toutes les versions instanciées du modèle? Obtenir le graphique d'héritage est assez facile, il existe un certain nombre d'outils qui l'exposent, y compris, par exemple, la sortie XML de Doxygen. Combinant cette information et l'application de certaines heuristiques devrait vous donner l'avertissement que vous recherchez.



0
votes

C'est la signification entière de la distribution dynamique: c'est dynamique, c'est-à-dire que cela est vérifié au moment de l'exécution non au moment de la compilation.

Le compilateur ne vérifie que si les classes coulées sont polymorphes. Si les classes ne sont pas polymorphes, il n'y aura pas assez d'informations pour vérifier la coulée au moment de l'exécution.

et enfin après que le programme dynamique doit vérifier si le pointeur reçu n'est pas nul. Si vous lancez à une référence, vous devriez attraper STD :: Bad_cast.


0 commentaires