2010-11-20 4 views
1

Wenn ich eine Basisklasse habe:Generieren einer abgeleiteten Klasseninstanz aus einer Zeichenfolge ihres Namens. (Dh Reflexion)

class Base 
{ 
public: 
virtual void Test()=0; 
}; 

und in einem dynamisch geladenen Modul (.so/DLL), implementiert I eine Klasse von diesem abgeleitet:

class SomethingFromBase : Base 
{ 
... 
}; 

und der Benutzer fragt, sobald diese Bibliothek geladen ist, eine Instanz von SomethingFromBase zu erstellen (sagen wir, wir bekommen den Namen von cin.), Und wir wissen nichts von SomethingFromBase (dh es gibt keine Möglichkeit, einfach if(inputstr == "SomethingFrombase") { ... } zu tun eine Möglichkeit, eine Instanz von SomethingFromBase zu erstellen?

Ich bin ziemlich sicher, dass dies in (Standard) C++ unmöglich ist, aber ich hoffe immer, dass SO mich überraschen wird!

Wenn dies mit der Zugabe von einigen Bibliotheken möglich ist, würde ich immer noch gerne darüber wissen. Danke!

Bearbeiten: Siehe cdhowies Antwort. Guides zur Umsetzung dieser Technik: http://www.linuxjournal.com/article/3687?page=0,1 http://www.abstraction.net/ViewArticle.aspx?articleID=67

Antwort

5

Sie erreichen dies typischerweise durch erforderlich, dass Plug-Bibliotheken eine globale Variable eines Strukturtyp definieren, die Zeiger enthält zu verschiedenen Funktionen, die Sie anrufen können. (Wie Setup, Teardown, etc.) Während der Setup-Funktion würden sie in Ihrer Anwendung zu einer "Register" -Funktion zurückkehren, wo sie eine Zeichenfolge übergeben könnten, die den Namen der Klasse darstellt, und einen Factory-Funktionszeiger, der ein Instanz bei Ausführung.

Sie verstauen dies in einer Karte, und wenn der Benutzer eine Zeichenfolge eingibt, sehen Sie in der Karte nach, ob eine Werksfunktion registriert ist. Wenn ja, ruf einfach an.

Also das ist nicht "wahre" Reflexion, aber Sie können es bis zu einem gewissen Grad manuell hacken. Siehe zum Beispiel Pidgin, das die Spezifikation von Protokoll-Plugins erlaubt, die viele Einträge in der Protokollliste liefern können.

EDIT:Here is a nifty guide um etwas ähnliches zu implementieren. Ich bin eher eine C-Person, also kann ich nicht garantieren, dass es wirklich genial ist oder so, aber auf den ersten Blick sieht es gut aus. Ich habe ähnliche Sachen in C unter Linux gemacht, und der grundlegende Ansatz funktioniert ziemlich gut.

+0

Ja, das ist die einzige Möglichkeit, die ich sehen kann, um dies zu erreichen. Sie müssen eine Art Registry verwalten, in der jeder neue Typ gespeichert und mit einer beliebigen Zeichenfolge verknüpft wird. –

+0

Ah, nett und vernünftig, und praktisch kein Overhead, da es keine "echte" Reflexion ist. Cooles Zeug. –

+0

Yup, nur der Overhead von Funktionszeigern. Schau dir auch den Leitfaden an, den ich gerade zu meiner Antwort hinzugefügt habe. – cdhowie

0

Lassen Sie eine Map die Objekte der Klasse speichern, die durch den Klassennamen angegeben werden. Alle Klassen, die auf diese Weise erstellt werden müssen, müssen von einer Basisklasse wie "Creatable" abgeleitet werden. Der Code zum Hinzufügen des Objekts der Klasse muss mit der Implementierung der Klasse angegeben werden.

//Creatable.h 
#define IMPLEMENT_CREATABLE(ClassName) \ 
    ObjectMap::Instance().Add(string(ClassName), new ClassName); 

//ObjectMap.h. This is a singleton 
class ObjectMap 
{ 
    ........... 
    map<string, Creatable *> myMap; 
    ........... 
public: 
    void Add(const string &className, Creatable *); 
    Creatable * Get(const string &className); 
}; 

//My Class.h 
class MyClass : public Creatable 
{ 
    ................ 
}; 

//My Class.cpp 
IMPLEMENT_CREATABLE(MyClass); 


//Client.cpp 
string className; 
cin>>className; 
Creatable *anObject = ObjectMap::Instance().Get(className); 
Verwandte Themen