Генерация производного экземпляра класса из строки его имени.(то есть отражение) - PullRequest
1 голос
/ 20 ноября 2010

Если у меня есть базовый класс:

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

и в динамически загружаемом модуле (.so / .dll) я реализовал класс, производный от этого:

class SomethingFromBase : Base 
{
...
};

и пользователь после загрузки этой библиотеки просит создать экземпляр SomethingFromBase (скажем, мы получаем имя из cin.), И мы не знаем SomethingFromBase (т.е. никак просто сделать if(inputstr == "SomethingFrombase") { ... } есть ли способ создать экземпляр SomethingFromBase?

Я вполне уверен, что это невозможно в (стандартном) C ++, но я всегда надеюсь, что ТАК удивит меня!

Если это возможно с добавлением некоторой библиотеки, я все еще хотел бы знать об этом Спасибо!

Редактировать: См. Ответ cdhowie. Руководства по реализации этой методики: http://www.linuxjournal.com/article/3687?page=0,1 http://www.abstraction.net/ViewArticle.aspx?articleID=67

Ответы [ 2 ]

5 голосов
/ 20 ноября 2010

Обычно это достигается тем, что библиотеки плагинов определяют некоторую глобальную переменную типа структуры, которая содержит указатели на различные функции, которые вы можете вызывать.(Как установка, разборка и т. Д.) Во время функции установки они вызывали бы обратно в ваше приложение некоторую функцию «регистра», где они могли бы передать строку, представляющую имя класса, и указатель фабричной функции, который создастэкземпляр при выполнении.

Вы прячете это на некоторой карте, а когда пользователь вводит строку, вы смотрите на карту, чтобы увидеть, есть ли зарегистрированная фабричная функция.Если это так, просто назовите его.

Так что это не «истинное» отражение, но вы можете в некоторой степени вручную взломать его.См., Например, Pidgin, который позволяет задавать плагины протокола, которые могут содержать много записей в списке протоколов.

РЕДАКТИРОВАТЬ: Вот отличное руководство дляреализовать нечто подобное.Я больше человек С, поэтому я не могу ручаться за то, что это действительно круто или что-то в этом роде, но на первый взгляд это выглядит хорошо.Я делал подобные вещи в C на Linux, и базовый подход работает довольно хорошо.

0 голосов
/ 20 ноября 2010

В карте хранятся объекты класса, обозначенные именем класса.Все классы, которые должны быть созданы таким образом, должны быть получены из некоторого базового класса, называемого что-то вроде «Creatable». Код для добавления объекта класса должен быть дан с реализацией класса.

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