0 / 0 / 2
Регистрация: 28.03.2014
Сообщений: 8

Шаблоны и функторы как callback для класса свойства объекта. Код работает - но не должен

14.09.2015, 15:39. Показов 1893. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте!
Хочу написать реализацию класса свойства на шаблоне. Т.е есть объект, он инициирует необходимые проперти, в графическом представлении это может быть текстовое поле или combobox, при изменении которого вызывается необходимый функтор. Рабочий код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include "stdafx.h"
struct IsEnabled
{
    bool operator()(void) { return true;}
};
struct IsVisible
{
    bool operator()(void) { return true;}
};
template<typename ClassName, bool (ClassName::*enabler)()>
struct Enabler
{
    ClassName *m_sender;
    bool operator()(void) { return ((*m_sender).*enabler)();}
};
template<typename ClassName,typename Type, Type (ClassName::*getter)()>
struct Getter
{
    ClassName * m_sender;
    Type operator()(){ return ((*m_sender).*getter)();}
};
template<typename ClassName,typename Type,void (ClassName::*setter)(Type )>
struct Setter
{
    ClassName *m_sender;
    void operator ()(Type val)
    { 
        ((*m_sender).*setter)(val);
    }
    Type m_val;
};
template<typename GetterFunctor, typename SetterFunctor,typename EnableFunctor = IsEnabled, typename VisibleFunctor = IsVisible>
class CProperty
{
    
public:
    GetterFunctor m_getter;
    SetterFunctor m_setter;
    EnableFunctor m_enabler;
    VisibleFunctor m_visible;
    bool getValue()
    {
        return m_getter();
    }
    void setValue(bool  val)
    {
        m_setter(val);
    }
    bool isEnabled()
    {
        return m_enabler();
    }
    bool isVisible()
    {
        return m_visible();
    }
};
class test
{
public:
    test()
    {
    }
    void initProps()
    {
        CProperty<Getter<test,bool,&test::getVal>,Setter<test,bool,&test::setVal>,Enabler<test,&test::enabler>> prop;
        prop.getValue();
        prop.isEnabled();
        prop.isVisible();
        prop.setValue(false);
    }
    
    bool getVal()
    {
        return true;
    }
    void setVal(bool b)
    {
    }
    bool enabler()
    {
        return true;
    }
    bool visible()
    {
        return true;
    }
};
int _tmain(int argc, _TCHAR* argv[])
{
    test s;
    s.initProps();
    return 0;
}
Как видно свойство опрашивает заданный функтор - getter, setter и т.д, а использование функторов позволяет сделать не всегда необходимые методы проверки свойства - редактируемо, видимо - методами по дефолту. Но, этот код работает, хотя в каждом функторе в дебаге m_sender= 0xCCCCCC - память неинициализированна. Следовательно вызов в функторе, например, Setter - ((*m_sender).*setter)(val); должно приводить к падению. Оптимизация выключена в опциях компилятора. Почему работает?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
14.09.2015, 15:39
Ответы с готовыми решениями:

Метод класса не работает как callback-функция
Всем привет! Помогите разобраться с синтаксисом. Есть gui-прога, в которой содержится функция TForm4::kau2_2_callback(float value) ...

Libcurl: как должен выглядеть callback?
Прежде, чем юзать libcurl.dll пробовал PyCurl, но тот почему-то все время валит Python. В итоге решил вызывать методы непосредственно из...

Код работает не так как должен
Читаю я значит книгу, а там вот такой код: prompt = &quot;\nTell me something, and I will repeat it back to you:&quot; prompt +=...

8
267 / 170 / 40
Регистрация: 25.08.2014
Сообщений: 1,087
Записей в блоге: 1
14.09.2015, 15:55
Цитата Сообщение от andrew_wk Посмотреть сообщение
Почему работает?
Потому что функции это не данные. Функция есть в файле? Всё что нужно для её вызова есть? Если ответ на оба вопроса утвердительный, то метод будет вызван. Фактически ты обращаешься к информации, получаемой из класса, а не объекта.
0
0 / 0 / 2
Регистрация: 28.03.2014
Сообщений: 8
14.09.2015, 16:03  [ТС]
Пока файл один. Что нужно для ее вызова - здесь немного недогоняю? Но мне кажется, я что-то не так делаю здесь - возможно нужно что-то подправить, чтобы небыло обращения по m_sender, который = 0xCCCCCC ? Можете подсказать?
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
14.09.2015, 16:55
Property ???

В языке C++ следует стараться использовать альтернативные приемы, поскольку данный паттерн не является естественным для языка и не может быть реализован полностью в соответствии со своей семантикой.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
14.09.2015, 17:01
Цитата Сообщение от andrew_wk Посмотреть сообщение
Почему работает?
Потому что у тебя нет обращения к данным ClassName. Указатель this передается в холостую и фактически не используется.
Цитата Сообщение от andrew_wk Посмотреть сообщение
Но мне кажется, я что-то не так делаю здесь - возможно нужно что-то подправить, чтобы небыло обращения по m_sender, который = 0xCCCCCC ?
Конечно неправильно. Ты должен по крайней мере инициализировать m_sender в конструкторе.
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
template<typename ClassName, bool (ClassName::*enabler)()>
struct Enabler
{
    ClassName *m_sender;
    bool operator()(void) { return ((*m_sender).*enabler)();}
 
    Enabler(ClassName * sender) : m_sender(sender) {}
};
template<typename ClassName,typename Type, Type (ClassName::*getter)()>
struct Getter
{
    ClassName * m_sender;
    Type operator()(){ return ((*m_sender).*getter)();}
    
    Getter(ClassName * sender) : m_sender(sender) {}
};
template<typename ClassName,typename Type,void (ClassName::*setter)(Type )>
struct Setter
{
    ClassName *m_sender;
    void operator ()(Type val)
    { 
        ((*m_sender).*setter)(val);
    }
    Type m_val;
 
    Setter(ClassName * sender) : m_sender(sender) {}
};
template<typename GetterFunctor, typename SetterFunctor,typename EnableFunctor = IsEnabled, typename VisibleFunctor = IsVisible>
class CProperty
{
    
public:
    GetterFunctor m_getter;
    SetterFunctor m_setter;
    EnableFunctor m_enabler;
    VisibleFunctor m_visible;
    template <typename T>
    CProperty(T * selfPtr) : m_getter(selfPtr), m_setter(selfPtr), m_enabler(selfPtr) 
    {}
 
    bool getValue()
    {
        return m_getter();
    }
    void setValue(bool  val)
    {
        m_setter(val);
    }
    bool isEnabled()
    {
        return m_enabler();
    }
    bool isVisible()
    {
        return m_visible();
    }
};
 
//.....................
 
    void initProps()
    {
        CProperty<Getter<test,bool,&test::getVal>,Setter<test,bool,&test::setVal>,Enabler<test,&test::enabler>> prop(this);
        prop.getValue();
        prop.isEnabled();
        prop.isVisible();
        prop.setValue(false);
    }
0
0 / 0 / 2
Регистрация: 28.03.2014
Сообщений: 8
14.09.2015, 17:35  [ТС]
Avazart - почти то что я хочу, но функторы позволят явно указывать setter'ы и getter'ы и не только. Меня вообще волнует именно возможность указать переменное число аргументов в
шаблоне.
DrOffset - спасибо! Да я в конструкторе CProperty пробовал инициировать функторы как m_getter(this) и компилятор падал при попытке собрать код.

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

Окончательный вариант:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "stdafx.h"
 
 
//Вызываются по-дефолту, если enabler и/или visible функтор не указаны 
template<typename ClassName>
struct IsEnabled
{
    ClassName *m_sender;
    IsEnabled(ClassName * name):m_sender(name){}
    bool operator()(void) { return true;}
};
 
template<typename ClassName>
struct IsVisible
{
    ClassName *m_sender;
    IsVisible(ClassName * name):m_sender(name){}
    bool operator()(void) { return true;}
};
 
 
template<typename ClassName, bool (ClassName::*enabler)()>
struct Enabler
{
    Enabler(ClassName * name){m_sender = name;}
    ClassName *m_sender;
    bool operator()(void) { return ((*m_sender).*enabler)();}
};
 
template<typename ClassName, bool (ClassName::*visible)()>
struct Visible
{
    Visible(ClassName * name):m_sender(name){}
    ClassName *m_sender;
    bool operator()(void) { return ((*m_sender).*visible)();}
};
 
 
template<typename ClassName,typename Type, Type (ClassName::*getter)()>
struct Getter
{
    Getter(ClassName * name):m_sender(name){}
    ClassName * m_sender;
    Type operator()(){ return ((*m_sender).*getter)();}
};
 
template<typename ClassName,typename Type,void (ClassName::*setter)(Type )>
struct Setter
{
    Setter(ClassName * name):m_sender(name){}
    ClassName *m_sender;
    void operator ()(Type val)
    { 
        ((*m_sender).*setter)(val);
    }
    Type m_val;
};
 
template<typename ClassName,typename GetterFunctor, typename SetterFunctor,typename EnableFunctor = IsEnabled<ClassName>, typename VisibleFunctor = IsVisible<ClassName>>
class CProperty
{
    
public:
    GetterFunctor m_getter;
    SetterFunctor m_setter;
    EnableFunctor m_enabler;
    VisibleFunctor m_visible;
 
    CProperty(ClassName  * obj):m_setter(obj),m_getter(obj),m_enabler(obj),m_visible(obj)
    {
    }
 
    bool getValue()
    {
        return m_getter();
    }
    void setValue(bool  val)
    {
        m_setter(val);
    }
 
    bool isEnabled()
    {
        return m_enabler();
    }
 
    bool isVisible()
    {
        return m_visible();
    }
};
 
 
 
class test
{
public:
 
    test()
    {
    }
    void initProps()
    {
        CProperty<test,Getter<test,bool,&test::getVal>,Setter<test,bool,&test::setVal>,Enabler<test,&test::enabler>,Visible<test,&test::visible>> *prop = new CProperty<test,Getter<test,bool,&test::getVal>,Setter<test,bool,&test::setVal>,Enabler<test,&test::enabler>,Visible<test,&test::visible>>(this);
        prop->getValue();
        prop->isEnabled();
        prop->isVisible();
        prop->setValue(false);
    }
    
    bool getVal()
    {
        return true;
    }
    void setVal(bool b)
    {
    }
    bool enabler()
    {
        return true;
    }
    bool visible()
    {
        return true;
    }
};
 
int _tmain(int argc, _TCHAR* argv[])
{
    test s;
    s.initProps();
    return 0;
}
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
14.09.2015, 17:49
Цитата Сообщение от andrew_wk Посмотреть сообщение
моя реализация имеет право на существование ?
Да все имеет, пока в продакшен не идет
Ладно - это шутка.
Если серьезно, то предлагаю начать с вариантов использования твоего решения. Напиши себе примеры так, как будто все уже сделано, с точки зрения пользователя. Тогда подводные камни и неудобства сразу будут видны.
Для обучения эта задача вполне подойдет.
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
14.09.2015, 18:27
Цитата Сообщение от andrew_wk Посмотреть сообщение
Avazart - почти то что я хочу, но функторы позволят явно указывать setter'ы и getter'ы и не только. Меня вообще волнует именно возможность указать переменное число аргументов в
Нифига не понял из сказанного... каким тут боком функтуры?
0
267 / 170 / 40
Регистрация: 25.08.2014
Сообщений: 1,087
Записей в блоге: 1
14.09.2015, 19:08
Цитата Сообщение от andrew_wk Посмотреть сообщение
Пока файл один.
Исполняемый, я имел ввиду.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
14.09.2015, 19:08
Помогаю со студенческими работами здесь

Этот код должен хранить «hellowor.d» как переменную под названием «Name», но она не работает
public static A = &quot;hello&quot;; public static B = &quot;wor.d&quot;; public static Name = A + B; Этот код должен хранить «hellowor.d» как...

Производный класс Самоорганизующаяся таблица должен наследовать свойства и методы класса Таблица
класс таблица, содержащий целые числа Обьект класса таблица должен позволять: 1 инициализировать случайными числами таблицу 2...

Как задать значение по умолчанию для свойства класса
Где и как можно сохранять и считывать значения свойств класса. Помню - такая возможность есть - но нет книжки под рукой Заранее благодарен

Как отменить свойства только для одной го элемента из класса?
http://rootedinisrael.org/ - создал для пунктов меню навигации нижнее подчеркивание при наведении, но все это распространяется и на...

Один и тот же код на С++ и С#, Шаблоны, отображение содержимого шаблонного класса
написан на С++ шаблонный класс &quot;List&quot; созданный для создания списковой структуры внутри двоичного файла () предусматривается работа с...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

Новые блоги и статьи
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: при выборе сотрудника (справочник Сотрудники) в ТЧ документа. . .
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
модель ЗдравоСохранения 8. Подготовка к разному выполнению заданий
anaschu 08.04.2026
https:/ / github. com/ shumilovas/ med2. git main ветка * содержимое блока дэлэй из старой модели теперь внутри зайца новой модели 8ATzM_2aurI
Блокировка документа от изменений, если он открыт у другого пользователя
Maks 08.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в конфигурации КА2. Задача: запретить редактирование документа, если он открыт у другого пользователя. / / . . .
Система безопасности+живучести для сервера-слоя интернета (сети). Двойная привязка.
Hrethgir 08.04.2026
Далее были размышления о системе безопасности. Сообщения с наклонным текстом - мои. А как нам будет можно проверить, что ссылка наша, а не подделана хулиганами, которая выбросит на другую ветку и. . .
Модель ЗдрввоСохранения 7: больше работников, больше ресурсов.
anaschu 08.04.2026
работников и заданий может быть сколько угодно, но настроено всё так, что используется пока что только 20% kYBz3eJf3jQ
Дальние перспективы сервера - слоя сети с космологическим дизайном интефейса карты и логики.
Hrethgir 07.04.2026
Дальнейшее ближайшее планирование вывело к размышлениям над дальними перспективами. И вот тут может быть даже будут нужны оценки специалистов, так как в дальних перспективах всё может очень сильно. . .
Горе от ума
kumehtar 07.04.2026
Эта мне ментальная установка, что вот прямо сейчас, мол, мне для полного счастья не хватает (нужное вписать), и когда я этого достигну - тогда и полный кайф. Одна из самых сильных ловушек на пути. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru