LINUX.ORG.RU

Неявное создание объектов в С++


0

0

Хочу реализовать что-то вроде механизма плагинов, пока не динамически
подключаемых.  Каждый плагин представляет собой класс имеющий метод 
run() внутри которого и будет выполняться полезная работа. Проблема в 
том что при запуске надо инициализировать GUI, т.е сообщить ему(ей)  
какие плагины в данный момент существуют, при этом сами объекты 
классов, реализующих плагины, еще не созданы.  
Для этого придумал такую конструкцию : 
class AbstractPlugin 
{ 
 public:   
 virtual void run()=0; 
 virtual string initGUI()=0; 
}; 
 
class PluginCtor 
{ 
 public: 
 virtual  AbstractPlugin * create()=0; 
 virtual void registerPlugin()=0;  
}; 
 
class PluginManager 
{ 
  friend class PluginCtor; 
 public: 
  static  vector<PluginCtor *> * theCtors; 
}; 
 
#define CREATECTOR(name) \ 
class Ctor##name : public PluginCtor { \ 
public: \ 
AbstractPlugin * create() { return new (##name)();} \ 
void registerPlugin() {PluginManager::theCtors->push_back(this);} \ 
Ctor##name() {registerPlugin();} \ 
}; \ 
static Ctor##name Ctor##name##_var; 
  
class RealPlugin : public AbstractPlugin 
{ 
 public: 
  void run(); 
  string initGUI(); 
}; 
  
Здесь все классы-плагины должны быть потомками AbstractPlugin, и в 
файле с реализацией (*.cpp) вызывать макрос CREATECTOR() со своим 
именем в качестве параметра. А дальше  в main() я пробегаю по массиву 
theCtors, создаю объект через create(), вызываю initGUI() и сразу же 
уничтожаю.   
А вопрос такой : как все это можно реализовать средствами С++ проще, по возможности без использования статических переменных(static Ctor##name Ctor##name##_var;), а лучше вообще без макросов.  Может кто-нибудь уже  делал что-то подобное? 

★★

Чтобы без макросов - можно использовать rtti. А вот без статических данных - сложно.

anonymous
()
Ответ на: комментарий от anonymous

А все-таки как прикрутить сюда rtti? я сним почти не знаком. Если можно хоть небольшой кусочек кода. можно на мыло vinick@mail.ru Пока поуйду читать Страуструпа.

Vinick ★★
() автор топика

RTTI тут нафиг не надо.
Вот те же яйца, только сбоку:
А вообще это у Страуструпа было, только слегка на другую тему.
--------------------------
#include <string>
#include <iostream>
#include <map>

using namespace std;

class IPlugin {
protected:
      IPlugin () {}
public:
      virtual ~IPlugin () {}
      static IPlugin *create () { };
      virtual void run () = 0;
};

typedef IPlugin* (*PluginFactory) ();

class PluginManager {
static map<string,PluginFactory> plugins;
public:
   PluginManager ()
   {
   }
   ~PluginManager () {
   }
   static void registerPlugin (string name, PluginFactory p) {
      plugins[name] = p;
   }
   static IPlugin* create (string name) {
      PluginFactory p = plugins [name];
      if (p) {
         return p ();
      }
      throw;
   }
};
map<string,PluginFactory> PluginManager::plugins;

class RealPlugin : public IPlugin
{
    RealPlugin () { }
public:
    static IPlugin* create () { return new RealPlugin (); }
    void run () { cout << "RealPlugin running" << endl; }
};

#define REGISTER_PLUGIN(x) \
   PluginManager::registerPlugin (#x, x::create)


int main ()
{
REGISTER_PLUGIN (RealPlugin);
   
   IPlugin* plg = PluginManager::create ("RealPlugin");
   plg->run ();
}

anonymous
()

2anonymous (*) (2003-02-21 01:59:14.843)
ochen' simpatichno,

no IMHO
PluginFactory p = plugins [name];
neskol'ko grubo, poskol'ku esli name net v map
to on budet sozdan,
find() budet korrektnee

anonymous
()
Ответ на: комментарий от anonymous

Вот оно оказывается как ! Оказывается можно переопределять статические методы !!! А я-то думал .... Большое спасибо. Открыли глаза.

Vinick ★★
() автор топика

> find() budet korrektnee

Ну, в данном коде это не существенно =-)
Но вообще да, корректность не помешает.

2Vinick

Всегда пожалуйста.

Кстати, этот код достаточно просто модифицировать для работы
с внешними плагинами. Достаточно объявить в модуле экспортируемую функцию, принимающую указатель на PluginManager::registerPlugin.
А потом через dlopen() открыть модуль (*.so) и вызвать эту функцию.
Модуль, естественно, компилить с -shared

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.