crossplatform.ru

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


  Ответ в Аналог Q_PROPERTY
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
 

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
Влад Дата 30.7.2009, 17:18
 
Цитата(igor_bogomolov @ 30.7.2009, 18:02) *
Достаточно ли просто сделать propMap.clear(); ???

А зачем его делать? (То есть, делать тоже не возбраняется, конечно же...) При разрушении объекта твоего класса будет вызван деструктор члена propMap (который по сути std::map<>), а деструктор этого члена (== деструктор std::map<>) корректно очистит все, что нужно.
BRE Дата 30.7.2009, 17:08
 
Цитата(igor_bogomolov @ 30.7.2009, 18:02) *
Достаточно ли просто сделать propMap.clear(); ???

Да.
igor_bogomolov Дата 30.7.2009, 17:02
  Вот что в результате получилось.
инклюдники и определения
#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(); ???
ViGOur Дата 30.7.2009, 15:22
 
Цитата(igor_bogomolov @ 30.7.2009, 15:12) *
ЗЫ. Тему лучше перенести в boost.
Перенес.
AD Дата 30.7.2009, 14:13
 
Цитата(igor_bogomolov @ 30.7.2009, 15:12) *
Осталось отвязаться от конкретных типов. Пока не понял что лучше использовать - boost::any или boost::variant ?

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

Мне пригодиться. :)
igor_bogomolov Дата 30.7.2009, 14:12
  BRE, спасибо огромнейшее. Все получилось. :rolleyes:

Осталось отвязаться от конкретных типов. Пока не понял что лучше использовать - boost::any или boost::variant ?

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


ЗЫ. Тему лучше перенести в boost.
BRE Дата 30.7.2009, 13:50
  Более подробный рабочий пример:
Раскрывающийся текст

#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>

class Base
{
public:
    typedef boost::function<bool (int)> SetFunc;
    typedef boost::function<int ()> GetFunc;

    Base() : m_value( 0 ) {}

    bool set( int val )
    {
    std::cout << "set=" << val << std::endl;
    m_value = val;
    return true;
    }

    int get()
    {
    return m_value;
    }

private:
    int    m_value;
};

int main( int, char ** )
{
    Base b;

    Base::SetFunc sf = boost::bind( &Base::set, &b, _1 );
    Base::GetFunc gf = boost::bind( &Base::get, &b );

    std::cout << "get=" << gf() << std::endl;
    sf( 100 );
    std::cout << "get=" << gf() << std::endl;
    
    return 0;
}

igor_bogomolov Дата 30.7.2009, 13:33
 
cpp
class base
{
public:
    base();
    virtual ~base();

    typedef function<bool (int)> SetFunc;
    typedef function<int ()> GetFunc;
    typedef pair<SetFunc, GetFunc> Set_Get_Pair;
    typedef map<string, Set_Get_Pair> PropertyMap;

    bool setProperty(const char* name, int value) {
        std::string str(name);
        PropertyMap::const_iterator i = propMap.find(str);
        ((i->second).first)(value);
        return true;
    }

    int property(const char* name) const {
        string str(name);
        PropertyMap::const_iterator i = propMap.find(str);
        return ((i->second).second)();
    }

protected:
    PropertyMap propMap;
    bool register_property(const char* name, SetFunc setprop, GetFunc getprop) {
        return propMap.insert(make_pair(string(name), Set_Get_Pair(setprop, getprop))).second;
    }
};


class device : public base
{
public:
    device() {
    SetFunc sf = bind(&device::setTestProp, this); // ошибка!!!!!
//    GetFunc gf = bind(&device::getTestProp);
//    register_property("Test", sf, gf);
    }

    bool setTestProp(int /*val*/) {
        return true;
    }

    int getTestProp() {
        return 125;
    }
};
вывод
Цитата
/usr/include/boost/bind/mem_fn.hpp: In member function ‘R& boost::_mfi::Dm<R, T>::operator()(T*) const [with R = bool ()(int), T = device]’:
/usr/include/boost/bind/bind.hpp:236: instantiated from ‘R boost::_bi::list1<A1>::operator()(boost::_bi::type<R>, F&, A&, long int) [with R = bool (&)(int), F = boost::_mfi::Dm<bool ()(int), device>, A = boost::_bi::list1<int&>, A1 = boost::_bi::value<device*>]’
/usr/include/boost/bind/bind_template.hpp:32: instantiated from ‘typename boost::_bi::result_traits<R, F>::type boost::_bi::bind_t<R, F, L>::operator()(A1&) [with A1 = int, R = bool (&)(int), F = boost::_mfi::Dm<bool ()(int), device>, L = boost::_bi::list1<boost::_bi::value<device*> >]’
/usr/include/boost/function/function_template.hpp:131: instantiated from ‘static R boost::detail::function::function_obj_invoker1<FunctionObj, R, T0>::invoke(boost::detail::function::function_buffer&, T0) [with FunctionObj = boost::_bi::bind_t<bool (&)(int), boost::_mfi::Dm<bool ()(int), device>, boost::_bi::list1<boost::_bi::value<device*> > >, R = bool, T0 = int]’
/usr/include/boost/function/function_template.hpp:904: instantiated from ‘void boost::function1<R, T1>::assign_to(Functor) [with Functor = boost::_bi::bind_t<bool (&)(int), boost::_mfi::Dm<bool ()(int), device>, boost::_bi::list1<boost::_bi::value<device*> > >, R = bool, T0 = int]’
/usr/include/boost/function/function_template.hpp:720: instantiated from ‘boost::function1<R, T1>::function1(Functor, typename boost::enable_if_c<boost::type_traits::ice_not::value, int>::type) [with Functor = boost::_bi::bind_t<bool (&)(int), boost::_mfi::Dm<bool ()(int), device>, boost::_bi::list1<boost::_bi::value<device*> > >, R = bool, T0 = int]’
/usr/include/boost/function/function_template.hpp:1040: instantiated from ‘boost::function<R ()(T0)>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not::value, int>::type) [with Functor = boost::_bi::bind_t<bool (&)(int), boost::_mfi::Dm<bool ()(int), device>, boost::_bi::list1<boost::_bi::value<device*> > >, R = bool, T0 = int]’
main.cpp:129: instantiated from here
/usr/include/boost/bind/mem_fn.hpp:342: error: invalid use of non-static member function


Что я опять делаю не так ???
BRE Дата 30.7.2009, 12:20
  Набросаю прямо здесь небольшой пример:
typedef boost::function<bool (int)> SetFunc;
typedef boost::function<int ()> GetFunc;

bool register_property(const char* name, SetFunc setprop, GetFunc getprop)
{
    ...
}
Влад Дата 30.7.2009, 12:16
  Посмотри, например, вот на это: http://www.progz.ru/forum/index.php?showtopic=27073&st=0
Просмотр темы полностью (откроется в новом окне)
RSS Текстовая версия Сейчас: 29.3.2024, 8:43