Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 30, средняя оценка - 4.97
sofen
0 / 0 / 0
Регистрация: 31.10.2010
Сообщений: 45
#1

Реализация событий в С++ - C++

02.11.2010, 08:56. Просмотров 4238. Ответов 15
Метки нет (Все метки)

Мне нужно реализовать события, как в Дельфи или С++ Builder, на Visual C++. Но стандартный С++ не поддерживает указатели на функции-члены класса. В своём блоге за 02.11.10, я попытался расписать, как это можно было бы реализовать, но получилось уж слишком громоздко... А как сделать проще?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.11.2010, 08:56     Реализация событий в С++
Посмотрите здесь:

Реализация ожжидания сразу двух событий - Boost C++
Допустим есть три потока, один из которыйх должен ждать наступления одного из двух событий и изходя из того какое сработает превым делать...

Реализация журнала ошибок и протоколирования событий - C++
Добрый день, уважаемое сообщество. При написании выпускной работы появилась необходимость вести журнал ошибок работы программы, и...

Тетрис - Реализация таймера и обработка событий с клавиатуры - C++
Пишу консольный тетрис. Столкнулся с проблемой таймера и перехвата событий с клавиатуры. Раньше с такими вопросами не сталкивался, поэтому...

Реализация программы на С++ (Найти вероятности следующих событий:) - C++
Помогите пожалуйста реализовать на С++ или на С# программу по этой задаче N стрелков независимо один от другого ведут стрельбу...

Журнал событий - Visual C++
Здраствуйте!! Запара втом что нужно написать програму з выкорыстанням функцыи: OpenBackupEventLog function -яка видкрывае журнал...

Добавление событий - C++ Builder
Как добавить событие в класс? предположим нужно событие которое возвращает строку и есть какой то такой класс: class TestClass { ...

Обработка событий - C++ Builder
Подскажите пожалуйста,как сделать какое -нибудь действие например ShowMessage для OnClick динамически создаваемых кнопок ...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
volovzi
267 / 169 / 8
Регистрация: 14.03.2010
Сообщений: 501
02.11.2010, 12:26     Реализация событий в С++ #2
Как это не поддерживает? Вот примеры:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <functional>
 
struct A {
    A (int y) : x(y) {}
 
    void print_x () const { std::cout << x << std::endl; }
    
    int x;
};
 
int main (int argc, char * const argv[]) {
    A a(17);
 
    typedef void (A::*method) () const;
    method fp = &A::print_x;
    
    (a.*fp)();
    //или
//  std::mem_fun(fp)(&a); // Этот вариант можно использовать и в алгоритмах.
 
    return 0;
}
Добавлено через 22 минуты
Полиморфизм:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <functional>
 
struct A {
    virtual void show () const { std::cout << "A::show()" << std::endl; }
};
 
struct B : A {
    void show () const { std::cout << "B::show()" << std::endl; }
};
 
int main (int argc, char * const argv[]) {
    A * a = new B;
 
    typedef void (A::*method) () const;
    method fp = &A::show;
    
//  (a->*fp)();
    //или
    std::mem_fun(fp)(a); // Этот вариант можно использовать и в алгоритмах.
 
    return 0;
}
Статические функции:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
 
struct A {
    static int get_num () { return 1; }
};
 
int main (int argc, char * const argv[]) {
    typedef int (* static_f_ptr) ();
    static_f_ptr fp = A::get_num;
 
    std::cout << fp() << std::endl;
 
    return 0;
}
CyBOSSeR
Эксперт C++
2300 / 1670 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
02.11.2010, 13:48     Реализация событий в С++ #3
sofen.ru, используй boost::function. Она может привязываться к свободным функциям, функторам, методам. И посмотри в сторону Boost.Signals.
sofen
0 / 0 / 0
Регистрация: 31.10.2010
Сообщений: 45
02.11.2010, 14:51  [ТС]     Реализация событий в С++ #4
void print_x () const { std::cout << x << std::endl; }
если убираю const, то не работает )

а мне надо вызывать ещё и виртуальную функцию)

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

К сожалению, админ удалил ссылку на мой блог ))) скидываю с него текст...


Реализация событий в С++

Опять столкнулся с проблемой, что в стандартном С++ нет указателя на функции, являющиеся членами класса (хотя есть указатель на обычную функцию). Для чего они могут понадобиться? На них можно было бы реализовать события, например, событие нажатия кнопки.

Пришлось пойти громоздким, но более-менее понятным путём. Для начала описываем класс события.

C++
1
2
3
4
5
6
7
8
9
10
11
template  class Event
{
public:
    Object *owner;
    T event;
    void set(Object *owner, T event)
    {
        this->owner = owner;
        this->event = event;
    }
};
Теперь опишем, тип “указатель на функцию”.

C++
1
typedef void (*ClickFunc)(Object *owner, Object *sender);
Затем, опишем тип «событие нажатия».

C++
1
typedef Event ClickEvent;
Ну пусть будет так… Как же теперь этим пользоваться?

Описываем классе кнопке Button событие onClick.

C++
1
2
3
4
class Button : Control {
public:
    ClickEvent onClick;
};
Во классе форме Form, где будет располагаться кнопка, описываем статическую функцию и обычную нормальную функцию, которую необходимо вызвать по событию.

C++
1
2
3
4
5
6
7
8
9
10
11
12
class Form {
public:
    static void stMyClick(Object *owner, Object *sender);
    virtual void myClick(Object *sender);
};
void Form::stMyClick(Object *owner, Object *sender) {
    ((CMy2*)owner)->myClick(Sender);
    
}
void Form::myClick(Object *sender) {
    //Код, выполняющийся по событию
}
Далее, в реализации какой-либо функции (или, например, в конструкторе) класса Form пишем следующее:

C++
1
2
Button *btn = new Button();
btn->onClick.set(this, stMyClick);
А уже в менеджере, который будет обрабатывать события, пишем следующее:

C++
1
if  (control->OnClick.event != NULL) control->OnClick.event(owner, sender);
Мдааа... Жесть...
volovzi
267 / 169 / 8
Регистрация: 14.03.2010
Сообщений: 501
02.11.2010, 15:26     Реализация событий в С++ #5
Цитата Сообщение от sofen Посмотреть сообщение
если убираю const, то не работает )
Епстессно, сигнатура же изменилась.

а мне надо вызывать ещё и виртуальную функцию)
Про виртуальные я уже писал.

полиморфизм и статические функции не катят)
Ты о чём?

буст тоже не подходит... Так как я пишу свою библиотеку, то завязывание на чужие либы (будь то буст или другая) никак не приемлемо... Я всем представляю либу, которая будет весить едва ли метр, но для её работы необходимо скачать несколько различных других библиотек на десятки или сотни килобайтов)))
Перед тем, как писать свою библиотеку, не мешало бы изучить имеющийся у человечества опыт.
sofen
0 / 0 / 0
Регистрация: 31.10.2010
Сообщений: 45
02.11.2010, 15:35  [ТС]     Реализация событий в С++ #6
volovzi, спасибо... не уверен, но вроде работает... сейчас разбираюсь...
tartikov
Заблокирован
02.11.2010, 15:54     Реализация событий в С++ #7
Цитата Сообщение от sofen Посмотреть сообщение
Мдааа... Жесть...
точно

информациии на эту тему - куча, прежде чем городить свой велосипед, надо что-нибудь почитать, посмотреть как сделано у других.

- boost::function, signals - уже советовали, наверно самое лучшее, и универсальное решение.
- Functor из книги Андрея Александреску.
- Гамма, "паттерны проектирования" - паттерн Command
- http://dobrokot.nm.ru/cpp/closure.zip - реализация от товарища Winnie, советую обратить особое внимание, если не хочешь тащить в проект тяжелые библиотеки вроде буста
sofen
0 / 0 / 0
Регистрация: 31.10.2010
Сообщений: 45
02.11.2010, 16:23  [ТС]     Реализация событий в С++ #8
volovzi, а как заставить работать следующий код?
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
#include <iostream>
 
class Object {
public:
    Object() {}
};
class Button : public Object {
public:
    Button() {}
    EventClick onClick; // Нужно перед этим как-то описать EventClick 
};
class Form : public Object {
public:
    Form() {}
    virtual void out(int value) { 
        std::cout << value << std::endl;
    }
};
int main(int argc, char* argv[])
{
    Form *form = new Form();
    Button *button = new Button();
    button->onClick = form->out; // Эта функция должна вызываться по событию onClick кнопки button
    button->onClick(10); // вызываем событие нажатия кнопки с каким-то параметром
    return 0;
}
tartikov, спасибо... кажись, то что и нужно... бум смотреть...
oxotnik
1589 / 1066 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
02.11.2010, 16:29     Реализация событий в С++ #9
Наблюдатель - паттерн
tartikov
Заблокирован
02.11.2010, 17:45     Реализация событий в С++ #10
Цитата Сообщение от sofen Посмотреть сообщение
а как заставить работать следующий код?
если использовать Winnie.Closure, то этот код будет выглядеть так
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
#include <iostream>
#include "closure.h"
 
class Object {
public:
    Object() {}
};
 
typedef Closure<void(int)> EventClick;
 
class Button : public Object {
public:
    Button() {}
    EventClick onClick; // Нужно перед этим как-то описать EventClick 
};
 
class Form : public Object {
public:
    Form() {}
    virtual void out(int value) { 
        std::cout << value << std::endl;
    }
};
 
int main(int argc, char* argv[])
{
    Form *form = new Form();
    Button *button = new Button();
    button->onClick = CLOSURE(form, &Form::out);
    button->onClick(10);
    return 0;
}
sofen
0 / 0 / 0
Регистрация: 31.10.2010
Сообщений: 45
02.11.2010, 22:55  [ТС]     Реализация событий в С++ #11
tartikov, ну что могу сказать... оно работает!

Посмотрел исходник closure.h и closure_impl.h - я в шоке!

Надо будет книжку полистать по С++ - загладить пробелы


Да, кстати, я слово CLOSURE заменил на getEvent, а Closure на Event ... теперь получилось симпотишно, как мне и надо было:

C++
1
2
3
4
5
typedef Event<void(int)> EventClick;
...
EventClick onClick;
...
button->onClick = getEvent(form, &Form::out);
tartikov
Заблокирован
03.11.2010, 00:15     Реализация событий в С++ #12
sofen, можно вопрос, а что у вас за класс Object, какие методы в него можно запихнуть, которые будут нужны всем объектам? Мне в голову ничего не приходит кроме как подсчет ссылок.
sofen
0 / 0 / 0
Регистрация: 31.10.2010
Сообщений: 45
03.11.2010, 10:19  [ТС]     Реализация событий в С++ #13
tartikov, методы runtime и сериализации...

Добавлено через 10 минут
Но это даже не главное. Главное, чтобы все мои классы были порождены от одного класса.

Спросите зачем? Уже и не помню. Вошло в привычку...

Добавлено через 4 часа 29 минут
tartikov, тут такой, на самом деле, очень важный вопрос... а как присвоить событию опять NULL ???
tartikov
Заблокирован
03.11.2010, 17:29     Реализация событий в С++ #14
Цитата Сообщение от sofen Посмотреть сообщение
tartikov, тут такой, на самом деле, очень важный вопрос... а как присвоить событию опять NULL ???
можно так
button->onClick = EventClick();
но тогда, при вызове приходится проверять
if(button->onClick) button->onClick(10);

Добавлено через 4 часа 35 минут
почему то в этой библиотеке у Closure нету оператора==.
если самому дописать его, то можно замутить такую штуку.
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
#include "closure.h"
#include <iostream>
#include <algorithm>
#include <vector>
 
template <class F>
class Signal
{
    typedef Closure<F> E; 
    typedef std::vector<E> EventsVector;
public:
 
    void operator+= (const E& event)
    {
        events.push_back(event);
    }
    void operator-= (const E& event)
    {
        events.erase(std::remove(events.begin(), events.end(), event), events.end());
    }
    void clear()
    {
        events.clear();
    }
 
    template<class A0>
    void operator()(const A0& a0)
    {
        for(EventsVector::iterator i = events.begin(); i != events.end(); ++i)
        {
            (*i)(a0);
        }
    }
    template<class A0, class A1>
    void operator()(const A0& a0, const A1& a1)
    {
        for(EventsVector::iterator i = events.begin(); i != events.end(); ++i)
        {
            (*i)(a0, a1);
        }
    }
    /* и так далее для стольки аргументов, сколько нужно*/
private:    
    EventsVector events;
};
 
 
class Form
{
public:
    void out1(int value) 
    { 
        std::cout << "out1 "<< value << std::endl;
    }
    void out2(int value) 
    { 
        std::cout << "out2 "<< value << std::endl;
    }
};
 
int main(int argc, char* argv[])
{
 
    Form form;
    Signal<void(int)> s;
    s += CLOSURE(&form, &Form::out1);
    s += CLOSURE(&form, &Form::out2);
    s(10);
    
    s -= CLOSURE(&form, &Form::out1);
    s(20);
    
    s.clear();
    s(30);
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.11.2010, 10:53     Реализация событий в С++
Еще ссылки по теме:

Журнал событий? - C++
надо создать что-то типа журнала событий. проблема в том чтобы вести хронологию. замучался с манами по localtime ctime и тд помогите...

Перегрузка обработчика событий - C++ Builder
Я хочу создать прямоугольное поле клеток (используя список). Сами &quot;клетки&quot; это просто наследники от кнопок, собственно кроме пары свойств,...

Трудности с созданием событий - Visual C++
Доброе утро. Возникли трудности с созданием событий. В общем-то, наверное в коде все понятно - есть 2 класса, необходимо, чтобы один...

Журнал событий Windows - C++ WinAPI
Необходимо написать программу на Winapi, которая будет считывать данные из Журнала событий Windows.

Общий обработчик событий - C++ Builder
Этот код взят из готового примера #include &lt;vcl.h&gt; #pragma hdrstop #include &quot;Unit1.h&quot; ...


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

Или воспользуйтесь поиском по форуму:
oxotnik
1589 / 1066 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
04.11.2010, 10:53     Реализация событий в С++ #15
Люди, выложите исходники Closure, а то чет по ссылке ничего не вижу. Страсть как охота посмотреть.
Yandex
Объявления
04.11.2010, 10:53     Реализация событий в С++
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru