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

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

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

Author24 — интернет-сервис помощи студентам
Здравствуйте!
Хочу написать реализацию класса свойства на шаблоне. Т.е есть объект, он инициирует необходимые проперти, в графическом представлении это может быть текстовое поле или 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
14.09.2015, 15:39
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 2
Цитата Сообщение от andrew_wk Посмотреть сообщение
Почему работает?
Потому что функции это не данные. Функция есть в файле? Всё что нужно для её вызова есть? Если ответ на оба вопроса утвердительный, то метод будет вызван. Фактически ты обращаешься к информации, получаемой из класса, а не объекта.
0
0 / 0 / 2
Регистрация: 28.03.2014
Сообщений: 8
14.09.2015, 16:03  [ТС] 3
Пока файл один. Что нужно для ее вызова - здесь немного недогоняю? Но мне кажется, я что-то не так делаю здесь - возможно нужно что-то подправить, чтобы небыло обращения по m_sender, который = 0xCCCCCC ? Можете подсказать?
0
Эксперт С++
 Аватар для Avazart
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
14.09.2015, 16:55 4
Property ???

В языке C++ следует стараться использовать альтернативные приемы, поскольку данный паттерн не является естественным для языка и не может быть реализован полностью в соответствии со своей семантикой.
0
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
14.09.2015, 17:01 5
Цитата Сообщение от 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  [ТС] 6
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
19409 / 10028 / 2443
Регистрация: 30.01.2014
Сообщений: 17,678
14.09.2015, 17:49 7
Цитата Сообщение от andrew_wk Посмотреть сообщение
моя реализация имеет право на существование ?
Да все имеет, пока в продакшен не идет
Ладно - это шутка.
Если серьезно, то предлагаю начать с вариантов использования твоего решения. Напиши себе примеры так, как будто все уже сделано, с точки зрения пользователя. Тогда подводные камни и неудобства сразу будут видны.
Для обучения эта задача вполне подойдет.
0
Эксперт С++
 Аватар для Avazart
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
14.09.2015, 18:27 8
Цитата Сообщение от andrew_wk Посмотреть сообщение
Avazart - почти то что я хочу, но функторы позволят явно указывать setter'ы и getter'ы и не только. Меня вообще волнует именно возможность указать переменное число аргументов в
Нифига не понял из сказанного... каким тут боком функтуры?
0
267 / 170 / 40
Регистрация: 25.08.2014
Сообщений: 1,087
Записей в блоге: 1
14.09.2015, 19:08 9
Цитата Сообщение от andrew_wk Посмотреть сообщение
Пока файл один.
Исполняемый, я имел ввиду.
0
14.09.2015, 19:08
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
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
Ответ Создать тему

Редактор формул (кликните на картинку в правом углу, чтобы закрыть)
Опции темы

Новые блоги и статьи
Микросервис с нуля на Go с Kafka
stackoverflow 12.02.2025
Когда я впервые столкнулся с необходимостью разделить монолитное приложение на микросервисы, передо мной встал вопрос выбора правильных технологий и подходов. После долгих экспериментов с различными. . .
Микросервис с нуля на C# с RabbitMQ
stackoverflow 12.02.2025
Переход от монолитной архитектуры к микросервисной - это не просто модное веяние, а закономерный этап эволюции программных систем. В отличие от монолита, где все компоненты тесно связаны между собой. . .
Docker для начинающих
stackoverflow 12.02.2025
В современном мире разработки программного обеспечения все чаще возникает необходимость быстро и надежно разворачивать приложения в различных средах. Разработчики постоянно сталкиваются с проблемой. . .
Создание бота для Телеграм на C#
stackoverflow 12.02.2025
В современном мире корпоративных коммуникаций Telegram-боты становятся незаменимым средством автоматизации бизнес-процессов и взаимодействия с сотрудниками. Как создать такого бота, который сможет. . .
Операторы сравнения (== и ===) в JavaScript
hw_wired 12.02.2025
JavaScript предоставляет два основных оператора сравнения - оператор нестрогого равенства (==) и оператор строгого равенства (===). На первый взгляд они могут показаться очень похожими, но их. . .
Определение адреса, откуда репозиторий Git был клонирован
hw_wired 12.02.2025
Система контроля версий Git хранит всю информацию о репозитории в специальной директории . git, включая данные об удаленных источниках. Эта информация необходима для синхронизации изменений между. . .
Объединение нескольких коммитов Git в один
hw_wired 12.02.2025
Представьте, что вы работаете над новой функциональностью и создали десяток небольших коммитов: исправление опечатки, форматирование кода, добавление комментариев, реализация основной логики. Каждый. . .
Как добавить локальную ветку в удалённый репозиторий Git
hw_wired 12.02.2025
Локальная ветка в Git - это изолированная линия разработки, существующая только на вашем компьютере. Представьте себе дерево с множеством веток - каждая ветка может расти в своем направлении, не. . .
Статическое отражение в C++
stackoverflow 12.02.2025
Статическое отражение представляет собой мощный механизм, позволяющий программам анализировать и манипулировать своей собственной структурой во время компиляции. Эта возможность открывает. . .
C++ в 21 веке - Бьярне Страуструп
stackoverflow 12.02.2025
В современном мире разработки программного обеспечения C++ продолжает оставаться одним из ключевых языков программирования, несмотря на свой солидный возраст - более 45 лет с момента создания. За это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru