Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Скрестить фабрику объектов и умные указатели 
V
    Опции темы
BasMan
Дата 11.3.2009, 21:48 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 5.7.2005

Репутация: нет
Всего: нет



Еще не сильно в шаблоны углубился, есть такой код:

Код

#define R(c) new CFactoryRegister<c>()

class CFactoryRegisterBase {
public:
  ~CFactoryRegisterBase() {};
  virtual void *Create() = 0;
};

template <class Class>
class CFactoryRegister : public CFactoryRegisterBase {
public:
  ~CFactoryRegister() {};
  void *Create() { return new Class(); };
};

template <class Base>
class CFactory
{
public:
  CFactory()
  {
    pthread_mutex_init(&lockmutex, 0);
  };
  ~CFactory()
  {
    pthread_mutex_destroy(&lockmutex);
  };

  u32 Count()
  {
    pthread_mutex_lock(&lockmutex);
    u32 ret=array.size();
    pthread_mutex_unlock(&lockmutex);
    return ret;
  };

  std::string Item(u32 index)
  {
    std::map<std::string, CFactoryRegisterBase*>::iterator p;

    pthread_mutex_lock(&lockmutex);
    p=array.begin();

    std::string tmp="";

    for (u32 i=0;p!=array.end();i++)
    {
      if (i==index)
      {
        tmp=p->first;
      };
      p++;
    };
    pthread_mutex_unlock(&lockmutex);

    return tmp;

  };

  void Register(CFactoryRegisterBase *reg, const std::string& name)
  {
    pthread_mutex_lock(&lockmutex);
    array[name] = reg;
    pthread_mutex_unlock(&lockmutex);
  };

  Base *Create(const std::string& name)
  {
    pthread_mutex_lock(&lockmutex);
    if(array[name])
    {
      pthread_mutex_unlock(&lockmutex);
      return (Base*)(array[name]->Create());
    };
    pthread_mutex_unlock(&lockmutex);
    return 0;
  };

private:
  std::map<std::string, CFactoryRegisterBase*> array;
  pthread_mutex_t lockmutex;
};



Как сюды можно прикрутить умные указатели? В частности auto_ptr?

Фабрика создается:
Код

    CFactory<clsExecutorInterface> *factory;
    factory=new CFactory<clsExecutorInterface>;


затем регистрируем на ней класс
Код

    factory->Register(R(clsExecutor), "test");


соответственно такое извращение не прокатит smile
Код

    CFactory<std::auto_ptr<clsExecutorInterface>> *factory;
    factory=new CFactory<std::auto_ptr<clsExecutorInterface>>;
    factory->Register(R(clsExecutor), "test");
    std::auto_ptr<clsExecutorInterface> a=factory->Create("test");

Основной вопрос, каким образом вместо базового класса объектов фабрики (clsExecutorInterface*) подсунуть  std::auto_ptr<clsExecutorInterface>, все мозги сломал уже smile

Заранее спасибо.

Это сообщение отредактировал(а) BasMan - 11.3.2009, 22:00
PM MAIL   Вверх
vinter
Дата 11.3.2009, 22:12 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата(BasMan @  11.3.2009,  22:48 Найти цитируемый пост)
есть такой код

сотри его, и перепиши с нуля


--------------------
Мой блог
PM MAIL WWW   Вверх
BasMan
Дата 12.3.2009, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 5.7.2005

Репутация: нет
Всего: нет



А если сделать еще один класс, который будет "контейнером" для clsExecutorInterface, и будет заниматься подсчетом количества ссылок и автоубиением экземпляра clsExecutorInterface? Помоему было бы неплохо.

p.s. У меня наследники clsExecutorInterface подгружаются из so библиотек, все вроде бы работает, но надоело постоянно приглядывать за указателями, а если проект будет разрастаться, то думаю будут неизбежны утечки памяти. 
PM MAIL   Вверх
azesmcar
Дата 12.3.2009, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата

Как сюды можно прикрутить умные указатели? В частности auto_ptr?


auto_ptr это не умный указатель. Умный указатель ведет подсчет ссылок, auto_ptr - нет. 


Код

#define R(c) new CFactoryRegister<c>()


как некрасиво smile
Код

return (Base*)(array[name]->Create());


этот каст ну ни к чему...

Код

class CFactoryRegisterBase {
public:
  ~CFactoryRegisterBase() {};
  virtual void *Create() = 0;
};
template <class Class>
class CFactoryRegister : public CFactoryRegisterBase {
public:
  ~CFactoryRegister() {};
  void *Create() { return new Class(); };
};


а это зачем нужно? вообще код ужасно надуманный и нечитабельный...
функция возвращяет void * притом что у тебя класс инстанцирован типом который тебе нужно вернуть, и вообще зачем этот класс? И даже не один а два..

Код

    CFactory<clsExecutorInterface> *factory;
    factory=new CFactory<clsExecutorInterface>;


что это??? почему не так
Код

CFactory<clsExecutorInterface> *factory=new CFactory<clsExecutorInterface>;


если тебе нужен auto_ptr - то пусть функция Create возвращает сразу auto_ptr..только не забывай в классе деструктор виртуальным сделать. А то auto_ptr его удалит по базовому указателю будет тебе memory leak.
PM   Вверх
azesmcar
Дата 12.3.2009, 14:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Код

template <class baseT>
class factory
{
    class objectCreator {
    public:
        virtual baseT* create() = 0;
    };

    template <class type>
    class concreteObjectCreator: public objectCreator {
    public:
        virtual baseT* create() {
            return new type();
        }
    };
public:
    //constructor
    factory() {}
    //destructor
    ~factory() {
        for (containerType::const_iterator it = container_.begin(); it != container_.end(); ++it)
            delete (it->second);
    }
    //register type
    template <class type>
    void registerType(const std::string& name) {
        container_.insert(containerType::value_type(name, new concreteObjectCreator<type>()));
    }
    //create object
    std::auto_ptr<baseT> create(const std::string& name) {
        containerType::const_iterator it = container_.find(name);
        if (it != container_.end())
            return std::auto_ptr<baseT>(it->second->create());
        
        throw std::runtime_error("type is not registered");
    }
private:
    typedef std::map<std::string, objectCreator*> containerType;
    containerType container_;
};


вот так хорошо?

Это сообщение отредактировал(а) azesmcar - 12.3.2009, 14:16
PM   Вверх
Fazil6
Дата 12.3.2009, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 35
Всего: 60



Код

#define R(c) new CFactoryRegister<c>()


дальше не читал. 
сразу фтопку... 
PM MAIL   Вверх
BasMan
Дата 12.3.2009, 16:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 5.7.2005

Репутация: нет
Всего: нет



Fazil6, глазами прочесть "в топку", а совершить кучу действий чтобы оставить пустой пост таки нужно было ;)

azesmcar спасибо, сегодня вечером попробую.

Код кстати не мой, не помню где нашел, просто в основном то все понятно с шаблонами, и простые реализация сам могу написать, а такое чтобы и фабрика и умные указатели сразу в одном, пока сложновато.

Это сообщение отредактировал(а) BasMan - 12.3.2009, 16:30
PM MAIL   Вверх
azesmcar
Дата 12.3.2009, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



BasMan, ну твой, не твой..а на минусы его указать стоит smile если запостил сюда, спрашиваешь как - значит собираешся его использовать..
удачи
PM   Вверх
jonie
Дата 13.3.2009, 09:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 15
Всего: 118



Цитата

auto_ptr это не умный указатель. Умный указатель ведет подсчет ссылок, auto_ptr - нет. 
это когда это умным стал только считаться смартуказатель с подсчетом ссылок?


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Lazin
Дата 13.3.2009, 09:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(azesmcar @  12.3.2009,  13:42 Найти цитируемый пост)
auto_ptr это не умный указатель. Умный указатель ведет подсчет ссылок, auto_ptr - нет. 

lolwhat?

Добавлено через 1 минуту и 41 секунду
я не понял, нужно чего-то добиться, или просто "прикрутить" умные указатели спортивного интереса ради? =)
PM MAIL Skype GTalk   Вверх
azesmcar
Дата 13.3.2009, 09:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата

это когда это умным стал только считаться смартуказатель с подсчетом ссылок? 


ну в принципе это термин, спорить тут бессмысленно. Я посмотрел, действительно для Smart Pointer ничего не сказано что он должен вести подсчет ссылок. Наверное откуда-то засело в памяти. Но это по моему не так актуально, называть его можно как угодно. В конце концов Элджер в своей книге вообще разделил на глупые, умные, мудрые и гениальные указатели.

Добавлено через 2 минуты и 5 секунд
Цитата

я не понял, нужно чего-то добиться, или просто "прикрутить" умные указатели спортивного интереса ради? =) 


вообще это красивое решение возвращять из фабрики умный указатель.
PM   Вверх
BasMan
Дата 14.3.2009, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 5.7.2005

Репутация: нет
Всего: нет



Время наконец то выдалось, проблема в следующем, компилятор (gcc 3.4.2) на данный код:

Код

template <class baseT>
class factory
{
    class objectCreator
    {
    public:
       virtual baseT* create() = 0;
    };


    template <class type>
    class concreteObjectCreator: public objectCreator
    {
    public:
        virtual baseT* create()
        {
            return new type();
        }
    };

private:
    typedef std::map<std::string, objectCreator*> containerType;
    containerType container_;

public:
    //constructor
    factory() {}

    //destructor
    ~factory()
    {
        for (containerType::const_iterator it = container_.begin(); it != container_.end(); ++it)
            delete (it->second);
    }
    //register type
    template <class type>
    void registerType(const std::string& name)
    {
        container_.insert(containerType::value_type(name, new concreteObjectCreator<type>()));
    }
    //create object
    boost::shared_ptr<baseT> create(const std::string& name)
    {
        containerType::const_iterator it = container_.find(name);
        if (it != container_.end())
            return boost::shared_ptr<baseT>(it->second->create());

        //throw std::runtime_error("type is not registered");
    }
};


ругается:

Код

src\interface.h||In destructor `factory<baseT>::~factory()':
src\interface.h|74|error: expected `;' before "it"
src\interface.h|74|error: `it' undeclared (first use this function)
src\interface.h|74|error: (Each undeclared identifier is reported only once for each function it appears in.)|

ну и т.д.


Как я понял он не видит objectCreator, причем CodeBlocks видит objectCreator, например в теле factory начинаешь набирать factory:: он вываливает список содержимого factory в т.ч. и objectCreator.
Если вынести из класса и объявить возвращаемый тип как void*:

Код

class objectCreator
{
public:
   virtual void* create() = 0;
};

template <class baseT>
class factory
{
    template <class type>
    class concreteObjectCreator: public objectCreator
    {
    public:
        virtual baseT* create()
        {
            return new type();
        }
    };

private:
    typedef std::map<std::string, objectCreator*> containerType;
    containerType container_;

public:
    //constructor
    factory() {}

    //destructor
    ~factory()
    {
        for (containerType::const_iterator it = container_.begin(); it != container_.end(); ++it)
            delete (it->second);
    }
    //register type
    template <class type>
    void registerType(const std::string& name)
    {
        container_.insert(containerType::value_type(name, new concreteObjectCreator<type>()));
    }
    //create object
    boost::shared_ptr<baseT> create(const std::string& name)
    {
        containerType::const_iterator it = container_.find(name);
        if (it != container_.end())
            return boost::shared_ptr<baseT>(it->second->create());

        //throw std::runtime_error("type is not registered");
    }
};


то все успешно компиляется

Это сообщение отредактировал(а) BasMan - 14.3.2009, 10:59
PM MAIL   Вверх
azesmcar
Дата 14.3.2009, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Код

    ~factory()
    {
        for (typename containerType::const_iterator it = container_.begin(); it != container_.end(); ++it)
            delete (it->second);
    }


Добавь typename перед обявлением итератора..я забыл
PM   Вверх
BasMan
Дата 14.3.2009, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 5.7.2005

Репутация: нет
Всего: нет



Итоговый вариант smile

Код

template <class baseT>
class factory
{

    class objectCreator
    {
    public:
       virtual baseT* create() = 0;
    };

    template <class type>
    class concreteObjectCreator: public objectCreator
    {
    public:
        virtual baseT* create()
        {
            return new type();
        }
    };

private:
    typedef std::map<std::string, objectCreator*> containerType;
    containerType container_;

public:
    //constructor
    factory() {}

    //destructor
    ~factory()
    {
        for (typename containerType::const_iterator it = container_.begin(); it != container_.end(); ++it)
            delete (it->second);
    }
    //register type
    template <class type>
    void registerType(const std::string& name)
    {
        container_.insert(typename containerType::value_type(name, new concreteObjectCreator<type>()));
    }
    //create object
    boost::shared_ptr<baseT> create(const std::string& name)
    {
        typename containerType::const_iterator it = container_.find(name);
        if (it != container_.end())
            return boost::shared_ptr<baseT>(it->second->create());

        throw std::runtime_error("type is not registered");
    }
};



Все вроде бы работает smile 
Большое спасибо, а код думаю еще кому-нибудь будет полезен.

p.s. Решил не поскупиться, заказал бумажный вариант книг Страуструпа и Александреску.

Это сообщение отредактировал(а) BasMan - 14.3.2009, 17:04
PM MAIL   Вверх
azesmcar
Дата 14.3.2009, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата

p.s. Решил не поскупиться, заказал бумажный вариант книг Страуструпа и Александреску. 


Сатера не забудь  smile 
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1485 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.