2009-05-12 19 views
12

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

5

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:

  1. 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.
  2. 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.

1

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.

+1

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

+2

@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. –

+1

Komplexe RTTI kann wie folgt aussehen: http://www.codeproject.com/KB/library/vcf_rtti.aspx – Francis

15

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).

0

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.

3

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.

1

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.

4

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.

0

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.

+0

Was bedeutet deine Antwort? Wo ist die anständige Implementierung, von der du sprichst? –

Verwandte Themen