Quelle est la méthode préférée pour obtenir l'équivalent C ++ de Java instanceof
?
java
c++
oop
instanceof
Yuval Adam
la source
la source
Réponses:
Essayez d'utiliser:
Cela nécessite que votre compilateur ait activé le support rtti.
EDIT: J'ai eu de bons commentaires sur cette réponse!
Chaque fois que vous devez utiliser un dynamic_cast (ou instanceof), vous feriez mieux de vous demander si c'est une chose nécessaire. C'est généralement un signe de mauvaise conception.
Les solutions de contournement typiques consistent à placer le comportement spécial de la classe que vous recherchez dans une fonction virtuelle sur la classe de base ou peut-être à introduire quelque chose comme un visiteur où vous pouvez introduire un comportement spécifique pour les sous-classes sans changer l'interface (sauf pour ajouter l'interface d'acceptation des visiteurs de cours).
Comme souligné, dynamic_cast n'est pas gratuit. Un hack simple et performant qui gère la plupart (mais pas tous les cas) consiste essentiellement à ajouter une énumération représentant tous les types possibles que votre classe peut avoir et à vérifier si vous avez le bon.
Ce n'est pas une bonne conception, mais cela peut être une solution de contournement et son coût n'est plus ou moins qu'un appel de fonction virtuelle. Il fonctionne également indépendamment du fait que RTTI soit activé ou non.
Notez que cette approche ne prend pas en charge plusieurs niveaux d'héritage, donc si vous ne faites pas attention, vous pourriez vous retrouver avec du code ressemblant à ceci:
la source
Selon ce que vous voulez faire, vous pouvez le faire:
Utilisation:
Cependant, cela fonctionne uniquement sur les types connus par le compilateur.
Éditer:
Ce code devrait fonctionner pour les pointeurs polymorphes:
Exemple: http://cpp.sh/6qir
la source
Instance de l'implémentation sans dynamic_cast
Je pense que cette question est toujours d'actualité. En utilisant la norme C ++ 11, vous pouvez désormais implémenter une
instanceof
fonction sans utiliserdynamic_cast
comme ceci:Mais vous dépendez toujours du
RTTI
support. Voici donc ma solution à ce problème en fonction de certaines macros et de la métaprogrammation magique. Le seul inconvénient à mon humble avis est que cette approche ne fonctionne pas pour l' héritage multiple .InstanceOfMacros.h
Démo
Vous pouvez ensuite utiliser ce truc ( avec prudence ) comme suit:
DemoClassHierarchy.hpp *
Le code suivant présente une petite démonstration pour vérifier rudimentairement le comportement correct.
InstanceOfDemo.cpp
Production:
Performance
La question la plus intéressante qui se pose maintenant est de savoir si ce truc diabolique est plus efficace que l’utilisation de
dynamic_cast
. J'ai donc écrit une application de mesure des performances très basique.InstanceOfPerformance.cpp
Les résultats varient et sont essentiellement basés sur le degré d'optimisation du compilateur. La compilation du programme de mesure des performances à
g++ -std=c++11 -O0 -o instanceof-performance InstanceOfPerformance.cpp
l' aide de la sortie sur ma machine locale était:Mhm, ce résultat était très décevant, car le timing démontre que la nouvelle approche n'est pas beaucoup plus rapide que l'
dynamic_cast
approche. Il est encore moins efficace pour le cas de test spécial qui teste si un pointeur deA
est une instance deA
. MAIS la marée tourne en ajustant notre binaire à l'aide de l'optimisation du compilateur. La commande de compilation correspondante estg++ -std=c++11 -O3 -o instanceof-performance InstanceOfPerformance.cpp
. Le résultat sur ma machine locale était incroyable:Si vous ne dépendez pas de l'héritage multiple, que vous n'êtes pas opposé aux bonnes vieilles macros C, au RTTI et à la métaprogrammation de modèles et que vous n'êtes pas trop paresseux pour ajouter de petites instructions aux classes de votre hiérarchie de classes, cette approche peut booster un peu votre application. en ce qui concerne ses performances, si vous finissez souvent par vérifier l'instance d'un pointeur. Mais utilisez-le avec prudence . Il n'y a aucune garantie quant à l'exactitude de cette approche.
Remarque: Toutes les démos ont été compilées à l'aide de
clang (Apple LLVM version 9.0.0 (clang-900.0.39.2))
macOS Sierra sur un MacBook Pro mi-2012.Edit: J'ai également testé les performances sur une machine Linux en utilisant
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
. Sur cette plateforme, l'avantage de la performance n'était pas aussi important que sur les macOs avec clang.Sortie (sans optimisation du compilateur):
Sortie (avec optimisation du compilateur):
la source
dynamic_cast
est connu pour être inefficace. Il traverse la hiérarchie d'héritage, et c'est la seule solution si vous avez plusieurs niveaux d'héritage et devez vérifier si un objet est une instance de l'un des types de sa hiérarchie de types.Mais si une forme plus limitée de
instanceof
cela vérifie seulement si un objet est exactement le type que vous spécifiez, suffit à vos besoins, la fonction ci-dessous serait beaucoup plus efficace:Voici un exemple de la façon dont vous appelleriez la fonction ci-dessus:
Vous devez spécifier le type de modèle
A
(comme le type que vous recherchez) et passer l'objet que vous souhaitez tester comme argument (à partir duquel le type de modèleK
serait déduit).la source
la source
instanceof
interroge le type dynamique, mais dans cette réponse, le type dynamique et statique correspondent toujours.Cela a fonctionné parfaitement pour moi en utilisant Code :: Blocks IDE avec GCC complier
la source
typeid
", ce qui, bien que faux ("Il n'y a aucune garantie que la même instance std :: type_info sera référencée par toutes les évaluations de l'expression typeid sur le même type ...assert(typeid(A) == typeid(A)); /* not guaranteed */
", voir cppreference.com ), indique qu'il a au moins essayé de répondre à la question, mais sans aide, car il a négligé d'offrir un exemple de travail minimal.