Was ist die bevorzugte Methode, um das C ++ - Äquivalent von Java zu erreichen instanceof
?
java
c++
oop
instanceof
Yuval Adam
quelle
quelle
Antworten:
Versuchen Sie es mit:
Dies setzt voraus, dass Ihr Compiler die Rtti-Unterstützung aktiviert hat.
EDIT: Ich habe einige gute Kommentare zu dieser Antwort gehabt!
Jedes Mal, wenn Sie einen dynamic_cast (oder eine Instanz davon) verwenden müssen, sollten Sie sich fragen, ob dies erforderlich ist. Es ist im Allgemeinen ein Zeichen für schlechtes Design.
Typische Problemumgehungen bestehen darin, das spezielle Verhalten für die Klasse, nach der Sie suchen, in eine virtuelle Funktion in der Basisklasse zu integrieren oder möglicherweise etwas wie einen Besucher einzuführen, in dem Sie ein bestimmtes Verhalten für Unterklassen einführen können, ohne die Schnittstelle zu ändern (außer das Hinzufügen der Besucherakzeptanzschnittstelle von Kurs).
Wie bereits erwähnt, ist dynamic_cast nicht kostenlos. Ein einfacher und konsistent ausführender Hack, der die meisten (aber nicht alle Fälle) behandelt, besteht im Grunde darin, eine Aufzählung hinzuzufügen, die alle möglichen Typen Ihrer Klasse darstellt, und zu prüfen, ob Sie den richtigen haben.
Dies ist kein gutes Design, aber es kann eine Problemumgehung sein und seine Kosten sind mehr oder weniger nur ein virtueller Funktionsaufruf. Es funktioniert auch unabhängig davon, ob RTTI aktiviert ist oder nicht.
Beachten Sie, dass dieser Ansatz nicht mehrere Vererbungsebenen unterstützt. Wenn Sie also nicht aufpassen, können Sie mit Code enden, der wie folgt aussieht:
quelle
Je nachdem, was Sie tun möchten, können Sie Folgendes tun:
Verwenden:
Dies funktioniert jedoch nur bei den dem Compiler bekannten Typen.
Bearbeiten:
Dieser Code sollte für polymorphe Zeiger funktionieren:
Beispiel: http://cpp.sh/6qir
quelle
Implementierungsinstanz ohne dynamic_cast
Ich denke, diese Frage ist heute noch relevant. Mit dem C ++ 11-Standard können Sie jetzt eine
instanceof
Funktion implementieren , ohne Folgendes zu verwendendynamic_cast
:Aber Sie sind immer noch auf
RTTI
Unterstützung angewiesen . Hier ist meine Lösung für dieses Problem, abhängig von einigen Makros und Metaprogrammiermagie. Der einzige Nachteil imho ist, dass dieser Ansatz nicht für Mehrfachvererbung funktioniert .InstanceOfMacros.h
Demo
Sie können dieses Zeug dann ( mit Vorsicht ) wie folgt verwenden:
DemoClassHierarchy.hpp *
Der folgende Code enthält eine kleine Demo, um das korrekte Verhalten rudimentär zu überprüfen.
InstanceOfDemo.cpp
Ausgabe:
Performance
Die interessanteste Frage, die sich jetzt stellt, ist, ob dieses böse Zeug effizienter ist als die Verwendung von
dynamic_cast
. Deshalb habe ich eine sehr einfache App zur Leistungsmessung geschrieben.InstanceOfPerformance.cpp
Die Ergebnisse variieren und basieren im Wesentlichen auf dem Grad der Compileroptimierung. Das Kompilieren des Leistungsmessprogramms unter Verwendung
g++ -std=c++11 -O0 -o instanceof-performance InstanceOfPerformance.cpp
der Ausgabe auf meinem lokalen Computer war:Mhm, dieses Ergebnis war sehr ernüchternd, da das Timing zeigt, dass der neue Ansatz im Vergleich zum
dynamic_cast
Ansatz nicht viel schneller ist . Es ist noch weniger effizient für den speziellen Testfall, der prüft, ob ein Zeiger vonA
eine Instanz von istA
. ABER das Blatt wendet sich, indem wir unsere Binärdatei mithilfe der Compiler-Otpimierung optimieren. Der jeweilige Compilerbefehl lautetg++ -std=c++11 -O3 -o instanceof-performance InstanceOfPerformance.cpp
. Das Ergebnis auf meinem lokalen Computer war erstaunlich:Wenn Sie nicht auf Mehrfachvererbung angewiesen sind, kein Gegner guter alter C-Makros, RTTI- und Vorlagen-Metaprogrammierung sind und nicht zu faul sind, um den Klassen Ihrer Klassenhierarchie einige kleine Anweisungen hinzuzufügen, kann dieser Ansatz Ihre Anwendung ein wenig verbessern in Bezug auf seine Leistung, wenn Sie häufig die Instanz eines Zeigers überprüfen. Aber verwenden Sie es mit Vorsicht . Es gibt keine Garantie für die Richtigkeit dieses Ansatzes.
Hinweis: Alle Demos wurden
clang (Apple LLVM version 9.0.0 (clang-900.0.39.2))
unter macOS Sierra auf einem MacBook Pro Mid 2012 kompiliert .Bearbeiten: Ich habe auch die Leistung auf einem Linux-Computer mit getestet
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
. Auf dieser Plattform war der Leistungsvorteil nicht so signifikant wie auf MacOs mit Clang.Ausgabe (ohne Compileroptimierung):
Ausgabe (mit Compileroptimierung):
quelle
dynamic_cast
ist als ineffizient bekannt. Es durchläuft die Vererbungshierarchie und ist die einzige Lösung, wenn Sie über mehrere Vererbungsebenen verfügen und prüfen müssen, ob ein Objekt eine Instanz eines der Typen in seiner Typhierarchie ist.Wenn jedoch eine eingeschränktere Form
instanceof
davon nur prüft, ob ein Objekt genau dem von Ihnen angegebenen Typ entspricht, der für Ihre Anforderungen ausreicht, ist die folgende Funktion viel effizienter:Hier ist ein Beispiel, wie Sie die obige Funktion aufrufen würden:
Sie geben den Vorlagentyp an
A
(als den Typ, nach dem Sie suchen) und übergeben das zu testende Objekt als Argument (aus dem der VorlagentypK
abgeleitet wird).quelle
quelle
instanceof
fragt den dynamischen Typ ab, aber in dieser Antwort stimmen der dynamische und der statische Typ immer überein.Dies funktionierte perfekt für mich mit Code :: Blocks IDE mit GCC-Konformität
quelle
typeid
" zu sein, was zwar falsch ist ("Es gibt keine Garantie dafür, dass bei allen Auswertungen des typeid-Ausdrucks auf demselben Typ auf dieselbe std :: type_info-Instanz verwiesen wird ...assert(typeid(A) == typeid(A)); /* not guaranteed */
", siehe cppreference.com ) gibt an, dass er zumindest versucht hat, die Frage zu beantworten, wenn auch nicht hilfreich, weil er es versäumt hat, ein minimales Arbeitsbeispiel anzubieten.