Gerando uma instância de classe derivada a partir de uma string de seu nome. (ou seja, reflexão)

StackOverflow https://stackoverflow.com/questions/4231205

Pergunta

Se eu tiver uma classe base:

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

e, em um módulo carregado dinamicamente (.so/.dll), implementei uma classe derivada disso:

class SomethingFromBase : Base 
{
...
};

E, o usuário, uma vez que esta biblioteca é carregada, pede para criar uma instância de SomethingFromBase (Digamos que obtemos o nome de Cin.) E, não temos conhecimento de SomethingFromBase (ou seja, não há como apenas fazer if(inputstr == "SomethingFrombase") { ... } Existe alguma maneira de criar uma instância de algo de fôlego?

Estou bastante certo de que isso é impossível no (padrão) C ++, mas estou sempre esperando que me surpreenda!

Se isso for possível com a adição de alguma biblioteca, eu ainda gostaria de saber sobre isso. Obrigado!

Editar: Veja a resposta de Cdhowie. Guias para implementar esta técnica:http://www.linuxjournal.com/article/3687?page=0,1http://www.abstraction.net/viewarticle.aspx?articleId=67

Foi útil?

Solução

Você normalmente consegue isso exigido por que as bibliotecas de plug -in defina alguma variável global de um tipo de estrutura que contém ponteiros para várias funções que você pode ligar. (Como configuração, desmontagem, etc.) Durante a função de configuração, eles ligariam de volta ao seu aplicativo para alguma função de "registro", onde eles poderiam passar em uma string representando o nome da classe e um ponteiro de função de fábrica que criará um instância quando executado.

Você esconde isso em algum mapa e, quando o usuário insere uma string, olha para o mapa para ver se há uma função de fábrica registrada. Nesse caso, basta chamar.

Portanto, isso não é uma reflexão "verdadeira", mas você pode invadi -la manualmente até certo ponto. Veja, por exemplo, Pidgin, que permite a especificação de plug -ins de protocolo que podem fornecer muitas entradas na lista de protocolos.

EDITAR: Aqui está um guia bacana para implementar algo semelhante. Eu sou mais uma pessoa C, então não posso garantir que seja realmente incrível ou algo assim, mas à primeira vista parece bom. Eu fiz coisas semelhantes em C no Linux, e a abordagem básica funciona muito bem.

Outras dicas

Peça a um mapa que os objetos da classe, digitados pelo nome da classe. Todas as classes que precisam ser criadas dessa maneira precisam ser derivadas de alguma classe base chamada algo como "Creatable", o código para adicionar o objeto da classe precisa ser dado com a implementação da 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 );
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top