2010-11-20 33 views
1

Si j'ai une classe de base:Génération d'une instance de classe dérivée à partir d'une chaîne de son nom. (C.-à-réflexion)

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

et, dans un module chargé dynamiquement (.so/dll), je mis en oeuvre une classe dérivée de celle-ci:

class SomethingFromBase : Base 
{ 
... 
}; 

et l'utilisateur, une fois que cette bibliothèque est chargée, demande de créer une instance de SomethingFromBase (disons que nous obtenons le nom de cin.), et nous ne connaissons pas SomethingFromBase (aucune façon de le faire juste if(inputstr == "SomethingFrombase") { ... } est là un moyen de créer une instance de SomethingFromBase?

Je suis assez certain que c'est impossible en C++ (standard), mais j'espère toujours que SO me surprendra!

Si cela est possible avec l'ajout d'une bibliothèque, je voudrais encore savoir. Merci!

Editer: Voir la réponse de cdhowie. Les guides de mise en œuvre de cette technique: http://www.linuxjournal.com/article/3687?page=0,1 http://www.abstraction.net/ViewArticle.aspx?articleID=67

Répondre

5

Vous établissent cette distinction en exigeait que les bibliothèques du plugin définissent une variable globale d'un type struct qui contient des pointeurs à diverses fonctions, vous pouvez appeler. (Comme configuration, démontage, etc.) Pendant la fonction d'installation, ils rappelleraient dans votre application à une fonction "registre" où ils pourraient transmettre une chaîne représentant le nom de la classe, et un pointeur de fonction d'usine qui créera un instance lors de l'exécution.

Vous Stash cette distance dans une carte, et lorsque l'utilisateur entre une chaîne, vous regardez la carte pour voir s'il y a une fonction d'usine enregistrée. Si oui, appelez-le.

Donc, ce n'est pas une réflexion « vrai », mais vous pouvez pirater manuellement dans une certaine mesure. Voir, par exemple, Pidgin, qui permet la spécification des plugins de protocole qui peuvent fournir de nombreuses entrées dans la liste des protocoles.

EDIT:Here is a nifty guide pour implémenter quelque chose de similaire. Je suis plus une personne C, donc je ne peux pas garantir qu'il soit vraiment génial ou quoi que ce soit, mais au premier coup d'œil ça a l'air bien. J'ai fait des choses similaires dans C sous Linux, et l'approche de base fonctionne plutôt bien.

+0

Oui, c'est la seule façon possible de voir cela. Vous devez maintenir une sorte de registre qui stocke chaque nouveau type et l'associe à une chaîne arbitraire. –

+0

Ah, gentil et sensé, et pratiquement pas de frais généraux, puisque ce n'est pas une "vraie" réflexion. Truc cool. –

+0

Yup, seul le surdébit des pointeurs de fonction. Aussi, consultez le guide que je viens d'ajouter à ma réponse. – cdhowie

0

ont un magasin de carte les objets de la classe, le nom calées de classe. Toutes les classes qui doivent être créés de cette façon, doivent provenir de quelque chose de classe de base nommée comme « Creatable » Le code pour ajouter l'objet de la nécessité de la classe à donner à la mise en œuvre de la classe.

//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);