crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V  < 1 2  
Ответить в данную темуНачать новую тему
> Аналог Q_PROPERTY
AD
  опции профиля:
сообщение 30.7.2009, 14:13
Сообщение #11


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(igor_bogomolov @ 30.7.2009, 15:12) *
Осталось отвязаться от конкретных типов. Пока не понял что лучше использовать - boost::any или boost::variant ?

Как обобщу, выложу готовый пример. Может еще кому пригодится :)

Мне пригодиться. :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 30.7.2009, 15:22
Сообщение #12


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Цитата(igor_bogomolov @ 30.7.2009, 15:12) *
ЗЫ. Тему лучше перенести в boost.
Перенес.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 30.7.2009, 17:02
Сообщение #13


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Вот что в результате получилось.
инклюдники и определения
#include <map>
#include <string>
#include <boost/function.hpp>
#include <boost/bind/bind.hpp>
#include <boost/variant.hpp>

using namespace std;
using namespace boost;

/// тип свойства
typedef boost::variant<int, string, double> Property_t;

/**
*  \def   REGISTER_PROPERTY(NAME, SETFUNC, GETFUNC)
*  \brief регистрация свойства экземпляра класса.
*
*  \var NAME    - имя свойства
*  \var SETFUNC - указатель на функцию установки свойства
*  \var GETFUNC - указатель на функцию чтения свойства
*/
#define REGISTER_PROPERTY(NAME, SETFUNC, GETFUNC) { \
    register_property( NAME, boost::bind(&SETFUNC, this, _1), boost::bind(&GETFUNC, this) ); \
}
класс Property
class Property
{
public:
    Property() {}       //!< Конструктор
    virtual ~Property() //!< Деструктор. Чистит все списки свойств
    {
        // а как память коректно очистить ???
        propMap.clear();
    }

public:
    /// Тип указателя на процедуру установки свойства
    typedef boost::function< bool (Property_t) > SetFunc;
    /// Тип указателя на процедуру чтения свойства
    typedef boost::function< Property_t ()     > GetFunc;
    /// Тип пары указателей на сетер и гетер
    typedef std::pair< SetFunc, GetFunc        > Set_Get_Pair;
    /// Тип отображения свойств
    typedef std::map< string, Set_Get_Pair     > PropertyMap;

public:
    /**
     *  \brief   Установить свойство.
     *
     *  \var     name  - имя свойства
     *  \var     value - значение
     *  \return  true при успешной установке свойства, иначе false.
     *  \warning Если свойство не найдено, генерируется исключение
     */
    bool setProperty(const char* name, Property_t value)
    {
        std::string str(name);
        PropertyMap::const_iterator i = propMap.find(str);
        if( i == propMap.end() ) {
            throw std::runtime_error("[setProperty] неизвестное свойство");
        }
        return ((i->second).first)(value);
    }

    /**
     *  \brief   Считать свойство.
     *
     *  \var     name - имя свойства
     *  \return  значение свойства
     *  \warning Если свойство не найдено, генерируется исключение
     */
    Property_t property(const char* name) const {
        std::string str(name);
        PropertyMap::const_iterator i = propMap.find(str);
        if( i == propMap.end() ) {
            throw std::runtime_error("[property] неизвестное свойство");
        }
        return ((i->second).second)();
    }

protected:
    PropertyMap propMap; //!< отображение свойств

    /**
     *  \brief Зарегистрировать свойство.
     *  \return true при удачной регистрации, иначе false
     */
    bool register_property(const char* name, SetFunc setprop, GetFunc getprop) {
        return propMap.insert(std::make_pair(string(name), Set_Get_Pair(setprop, getprop))).second;
    }
};
объявление классов для тестирования
class Test1 : public Property
{
public:
    Test1() {
        REGISTER_PROPERTY("Test", Test1::setTestProp, Test1::getTestProp);
    }
    bool setTestProp(Property_t /*val*/) {
        return true;
    }
    Property_t getTestProp() {
        return 125;
    }
};

class Test2 : public Property
{
public:
    Test2() {
        REGISTER_PROPERTY("Test", Test2::setTestProp2, Test2::getTestProp2);
    }
    bool setTestProp2(Property_t /*val*/) {
        return true;
    }
    Property_t getTestProp2() {
        return "string";
    }
};

class Test3 : public Property
{
public:
    Test3() {
        REGISTER_PROPERTY("Test", Test3::setTestProp3, Test3::getTestProp3);
    }
    bool setTestProp3(Property_t /*val*/) {
        return true;
    }
    Property_t getTestProp3() {
        return 1.89;
    }
};
main
int main(int /*argc*/, char** /*argc*/)
{
    Property* b[] = { new Test1, new Test2,  new Test3 };
    for(int i = 0; i != 3; i++ )
        cout <<"Property_t = " << b[i]->property("Test") << std::endl;

    return EXIT_SUCCESS;
}
результат
Цитата
Property_t = 125
Property_t = string
Property_t = 1.89


Для чего это нужно, думаю и так понятно. Что бы имея указатель только на базовый класс, получить доступ к любому методу порожденного от него класса.

У меня еще остался вопрос, по поводу очистки памяти в деструкторе. Достаточно ли просто сделать propMap.clear(); ???
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 30.7.2009, 17:08
Сообщение #14


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(igor_bogomolov @ 30.7.2009, 18:02) *
Достаточно ли просто сделать propMap.clear(); ???

Да.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Влад
  опции профиля:
сообщение 30.7.2009, 17:18
Сообщение #15


Участник
**

Группа: Участник
Сообщений: 146
Регистрация: 20.3.2009
Из: Санкт-Петербург
Пользователь №: 627

Спасибо сказали: 46 раз(а)




Репутация:   8  


Цитата(igor_bogomolov @ 30.7.2009, 18:02) *
Достаточно ли просто сделать propMap.clear(); ???

А зачем его делать? (То есть, делать тоже не возбраняется, конечно же...) При разрушении объекта твоего класса будет вызван деструктор члена propMap (который по сути std::map<>), а деструктор этого члена (== деструктор std::map<>) корректно очистит все, что нужно.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V  < 1 2
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 26.11.2024, 6:02