Ich arbeite seit Jahren mit Java. In diesen Jahren habe ich intensiv (oder vielleicht nur häufig) über Reflexion nachgedacht und sie als nützlich und unterhaltsam empfunden. Aber vor 8 Monaten habe ich meinen Job geändert, und jetzt ist Java nur noch eine Erinnerung und ich bekomme C++ in die Hände. Jetzt frage ich mich, ob es in C++ einen Reflexionsmechanismus gibt. Ich habe über RTTI gelesen, aber ich denke, es ist keineswegs die Stärke von Java (oder anderen Sprachen). Ich beginne zu denken, dass es in C++ keine Möglichkeit gibt, das zu tun. Liege ich falsch?Reflektion in C++
Antwort
Wenn Sie nach einem ganz allgemein aussehenden Objekten zur Laufzeit zu manipulieren, wenn Sie bei der Kompilierung ihre Typen in C++ nicht wissen, Sie im Wesentlichen zu müssen:
- definieren eine Schnittstelle (abstrakte Basisklasse mit allen reinen virtuellen Methoden und ohne Mitglieder) für jede Fähigkeit, die eine Klasse unterstützen könnte.
- Jede Klasse muss virtuell von allen Schnittstellen erben, die sie implementieren möchte (möglicherweise unter anderen Klassen).
Nun nehmen wir pFoo
Zeiger vom Typ einer Schnittstelle hält IFoo*
auf ein Objekt x
(Sie brauchen nicht x
‚s konkreter zu kennen). Sie können sehen, ob dieses Objekt Schnittstelle IBar
mit den Worten unterstützt:
if (IBar* pBar = dynamic_cast<IBar*>(pFoo)) {
// Do stuff using pBar here
pBar->endWorldHunger();
} else {
// Object doesn't support the interface: degrade gracefully
pFoo->grinStupidly();
}
Dieser Ansatz setzt voraus, Sie kennen alle relevanten Schnittstellen bei der Kompilierung - wenn Sie nicht tun, werden Sie nicht in der Lage sein, normale C++ Syntax für den Aufruf von Methoden sowieso. Aber es ist schwer, sich eine Situation vorzustellen, in der das aufrufende Programm nicht weiß, was Schnittstellen es braucht - über den einzigen Fall, den ich denken könnte, wenn Sie C++ Objekte über einen interaktiven Interpreter verfügbar machen wollen. Selbst dann können Sie eine (hässliche, wartungsintensive) Methode entwickeln, um dies in das obige Paradigma zu schüren, so dass Methoden aufgerufen werden können, indem ihre Namen und Argumente als Strings angegeben werden.
Der andere zu betrachtende Aspekt ist Objekterstellung. Um dies zu erreichen, ohne konkrete Typen zu kennen, benötigen Sie eine Factory-Funktion sowie eindeutige Bezeichner für Klassen, um anzugeben, welche konkrete Klasse Sie verwenden möchten. Es ist möglich, dass Klassen sich beim Start mit einer globalen Fabrik registrieren, as described here by C++ expert Herb Sutter - dies vermeidet die Beibehaltung einer gigantischen switch
-Anweisung, was die Wartung erheblich erleichtert. Es ist möglich, eine einzelne Factory zu verwenden, obwohl dies bedeutet, dass es eine einzige Schnittstelle gibt, die jedes Objekt in Ihrem System implementieren muss (die Factory wird einen Zeiger oder Verweis auf diesen Schnittstellentyp zurückgeben).
Am Ende des Tages, was Sie mit Wind-up ist im Grunde (isomorph) COM-dynamic_cast<IFoo*>
die gleiche Arbeit wie QueryInterface(IID_IFoo)
der Fall ist, und die Basis-Schnittstelle von allen Objekten implementiert entspricht IUnknown
.
RTTI ist eine Lösung (welcher Teil von Java ist Ihrer Meinung nach nicht in RTTI?), Andernfalls können Sie Ihr eigenes Objektrahmenwerk implementieren - jedes eigene C++ Objekt erbt irgendeine Reflexionsschnittstelle, und dann sollte es funktionieren.
Da der C++ - Standard ein solches Konzept nicht als "Metadaten" behandelt, gibt es keine andere Methode (über andere Compiler und Plattformen hinweg) als die RTTI, die Sie bereits erwähnt haben.
In C++ gibt es auch eine Möglichkeit der Kompilierung Reflektion (Think boost::type_traits
und boost::type_of
), aber es ist auch im Vergleich zu etwa Nemerle oder LISP begrenzt.
Die meisten wichtigen Frameworks (MFC, Qt usw.) ermöglichen es Ihnen, Metainformationen zur Laufzeit zu extrahieren, aber sie erfordern alle Arten von speziellen Annotationen, damit sie funktionieren (siehe RUNTIME_CLASS et al als Beispiel).
Wenn Sie es nur für die Abhängigkeitsinjektion verwenden (eine Implementierung einer Schnittstelle^H^H^H^H^H^reine abstrakte Klasse), könnten Sie das dynamische Laden von .dll- oder .so-Dateien versuchen, die enthalten die Implementierung des Tages für was auch immer der Stecker ist.
Wahrscheinlich nur am Strohhalm greifen, da dies für mehrere Implementierungen von Dingen zur gleichen Zeit nicht gut funktionieren wird.
Sie müssen das Besuchermuster verwenden. Jede Klasse, die reflektiert werden kann, müsste eine Basisklasse erben, die ihr eine Reflect
Mitgliedsfunktion gibt, die eine Besucherklasse akzeptiert. Dann würde die Funktion Reflect
Informationen oder Fähigkeiten über die anderen Mitglieder an den Besucher weitergeben.
Viele populäre Bibliotheken verwenden dieses Muster für bestimmte Fälle, zum Beispiel die Serialize
Funktion in MFC tut dies aber speziell für die Serialisierung.
Sie könnten ein System wahrscheinlich so entwerfen, dass der Besucher dynamische Aufrufe von Elementfunktionen vornehmen kann, die Werte von Datenelementen usw. abrufen oder festlegen können. Es wäre jedoch Aufgabe der einzelnen Klassen, diese zu verwalten eine Reflect
Funktion von Hand geschrieben, die eine Wiederholung der Struktur der Klasse wäre.
Reflexion ist der Prozess, mit dem ein Computerprogramm seine eigene Struktur und sein Verhalten beobachten und verändern kann. Ich sehe nicht, wie Sie Reflektion in C++ machen können. RTTI ist nur für den Datentyp des Objekts im Speicher zur Laufzeit nützlich.
Werfen Sie einen Blick auf my answer to a similar question. Beide vorgeschlagenen Lösungen (XRTTI und OpenC++) basieren auf externen Tools, die während des Erstellungsprozesses die Reflektions-Metadaten für Sie generieren.
Was müssen Sie in C++ tun und mit welcher Plattform arbeiten Sie? Ich kenne eine Möglichkeit, die vollständigen Klassendefinitionen zu erhalten und Funktionen aufzurufen, die diese Daten verwenden. Sie funktioniert unter Windows, aber ich weiß nichts über andere Plattformen. Die Idee ist, Daten aus der DLL oder Exe-Export-Tabelle zu nehmen. Es ist nicht einfach - wir haben mehrere Monate Arbeit gebraucht, um eine anständige Implementierung zu bekommen - aber es wird alles tun, was reflektionsunterstützende Sprachen tun.
Was bedeutet deine Antwort? Wo ist die anständige Implementierung, von der du sprichst? –
- 1. Einfache Reflektion Frage C#
- 2. Objective-C-Reflektion für generische NSCoding-Implementierung
- 3. C# Reflektion, Ändern des Körpers einer Methode
- 4. C# Reflektion - Get-Eigenschaft eines Objekts
- 5. Attribute aus C# Quellcode ohne Reflektion extrahieren
- 6. Dynamische Bindung an C# -Ereignisse mit Reflektion
- 7. C# Buddy-Klassen/Meta-Daten und Reflektion
- 8. Verwenden von Scala-Reflektion mit Java-Reflektion
- 9. Sind anonyme Typen in C# durch Reflektion zugänglich?
- 10. Convert func zu Prädikat mit Reflektion in C#
- 11. Reflektion auf einer Scala-Fallklasse
- 12. C++ (Semi) Reflektion für Datei speichern/laden? (Hack?)
- 13. java.lang.SecurityException mit Reflektion
- 14. C# - Erhalte benutzerfreundliche Namen einfacher Typen durch Reflektion?
- 15. C# Portable Klassenbibliothek und Reflektion mit geschachtelten Eigenschaften
- 16. C# - Werttyp Gleichwertige Methode - warum verwendet der Compiler die Reflektion?
- 17. Casting-Fehler mit Reflektion
- 18. Reflektion in einer Windows 8 App
- 19. C# Reflektion, Festlegen einer neuen Instanz einer Null-Eigenschaft
- 20. C# Reflektion Feld oder Eigenschaft nach Name erhalten
- 21. Java-Reflektion - Zugriffsschutzfeld
- 22. Java-Reflektion für Generika
- 23. C# mit Reflektion für den Zugriff auf Fenstereigenschaften
- 24. Probleme Aufruf statische Methode mithilfe von Reflektion und C#
- 25. Übereinstimmende Typen mit Reflektion in .NET
- 26. In 3 Minuten, Was ist Reflektion?
- 27. Problem mit Reflektion in Unit/Integration Tests
- 28. Unterschied zwischen RTTI und Reflektion in Java
- 29. Entfernen von Routingereignishandlern durch Reflektion?
- 30. Gibt es eine Möglichkeit, eine Reflektion in Javascript zu machen, aber die Unterseite der Reflektion wegzulassen?
Ich denke, mein Wissen über RTTI ist schlecht ... aber gibt es eine Möglichkeit, eine Liste von Methoden oder Attributen eines Objekts mit RTTI zu bekommen? – aitor
@aitor: Nein, das glaube ich nicht. RTTI kann Ihnen zur Laufzeit den Typ eines Objekts mitteilen, aber es liegt in Ihrer Verantwortung, diese Informationen in präzisere umzuwandeln, z. B. die Verfügbarkeit von Methoden und Attributen. –
Komplexe RTTI kann wie folgt aussehen: http://www.codeproject.com/KB/library/vcf_rtti.aspx – Francis