Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Есть ли события в С++?.. или их аналог?.. 
:(
    Опции темы
Kurt
Дата 11.9.2005, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлеченный
***


Профиль
Группа: Участник Клуба
Сообщений: 1662
Регистрация: 22.8.2003
Где: Краснодар

Репутация: нет
Всего: 36



Блуждая в поисках работы (ну не везет мне пока! smile ), наткнулся на задание реализовать простенькую игрушку - одна фигрука (управляемая компьютером) пытается в лабиринте настигнуть другую фигурку (управляется игроком). Естественно, нужно было уметь пересчитывать траекторию движения автоматической фигурки как только юзер изменил положение своей фигурки.
Первоначально просили сделать на С++, но в итоге сошлись на C#. (smile) Проблема пересчета траектории была решена через события. Как только "ручной" объект перешел на другую клетку лабиринта, генерится событие, к-е обрабатывается "автоматическим" объектом - заново вычисляется путь.
Задание сделал и отправил. Теперь вот думаю, как бы я решил эту задачу на С++.
Подскажите, пожалуйста, есть ли в С++ что-то подобное событиям? То есть мне надо чтобы один объект при наступлении некоторых условий генерировал событие, а другой - реагировал на него. Если можете показать пример, как это сделать - вообще здорово..


--------------------
Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед)
...
Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн)
PM ICQ   Вверх
srd
Дата 11.9.2005, 19:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


Профиль
Группа: Участник Клуба
Сообщений: 951
Регистрация: 30.8.2003
Где: Владивосток

Репутация: 27
Всего: 49



Существуют разные реализации схемы сигнал/слот. Например, boost::signals или libsigc++


--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
Void
Дата 11.9.2005, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Пример кода с использованием Boost.Signals и Boost.Bind:
Код
#include <iostream>

#include <boost/signal.hpp>
#include <boost/bind.hpp>

class EventProducer {
    typedef boost::signal<void(int)> signal_t;
    typedef boost::signals::connection connection_t;
    signal_t sig_;
    int x_;
public:
    EventProducer(int x) : x_(x) { }
    void fire_event() {
        std::cout << "Event fired: x = " << x_ << std::endl;
        sig_(x_);
    }
    connection_t connect(signal_t::slot_function_type subscriber) {
        return sig_.connect(subscriber);
    }
};

class EventConsumer {
    int id_;
public:
    EventConsumer(int id) : id_(id) { }
    void process_event(int x) {
        std::cout << "Event consumed: x = " << x << ", id = " <<
            id_ << std::endl;
    }
};

int main() {
    using namespace boost::signals;
    EventProducer obj(3);
    EventConsumer obj1(1), obj2(2);
    obj.connect(boost::bind(&EventConsumer::process_event, &obj1, _1));
    connection c2 =
        obj.connect(boost::bind(&EventConsumer::process_event, &obj2, _1));
    obj.fire_event();
    c2.disconnect();
    obj.fire_event();
}

Вывод:
Код
Event fired: x = 3
Event consumed: x = 3, id = 1
Event consumed: x = 3, id = 2
Event fired: x = 3
Event consumed: x = 3, id = 1



--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
chipset
Дата 12.9.2005, 03:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4071
Регистрация: 11.1.2003
Где: Seattle, US

Репутация: 27
Всего: 165



Исключения можешь бросать и ловить другими классами.
А вообще просто закидываешь делегат и вызываешь при необходимости (вариант лучше) smile


--------------------
Цитата(Jimi Hendrix)
Well, I stand up next to a mountain
And I chop it down with the edge of my hand
PM MAIL WWW   Вверх
Void
Дата 12.9.2005, 06:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Цитата(chipset @ 12.9.2005, 05:45)
Исключения можешь бросать и ловить другими классами.

Это как (в контексте задачи)? smile


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
chipset
Дата 12.9.2005, 07:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4071
Регистрация: 11.1.2003
Где: Seattle, US

Репутация: 27
Всего: 165



Цитата(Void @ 11.9.2005, 20:31)
Это как (в контексте задачи)?

Перечитал, понял - в контексте задачи никак, да и не красиво это, в общем smile


--------------------
Цитата(Jimi Hendrix)
Well, I stand up next to a mountain
And I chop it down with the edge of my hand
PM MAIL WWW   Вверх
Guest
Дата 12.9.2005, 08:47 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Это можно и без boost делаеть . См паттерн Chain of Responsibility.
Но в вашем случае всего то два объекта, один из которых генерит запрос, другой обрабатывает. Это вообще элементарно
  Вверх
oleg1973
Дата 12.9.2005, 10:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


asm fanat
****


Профиль
Группа: Экс. модератор
Сообщений: 3283
Регистрация: 16.7.2003
Где: Italy

Репутация: 1
Всего: 34



чет вы перемудрили слишком
что мешает сделать 2 процедуры - первая для "ручного" обьекта а вторая для автоматического и гонять их в цикле?
какие нафиг события?

п.с.
куда катится мир?


--------------------
SST 465555
icq 200-512-712
PM MAIL WWW ICQ   Вверх
Ignat
Дата 12.9.2005, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Флудератор
****


Профиль
Группа: Экс. модератор
Сообщений: 4030
Регистрация: 19.4.2004
Где: غيليندزيك مدينة

Репутация: 3
Всего: 73



Цитата(oleg1973 @ 12.9.2005, 11:09)
гонять их в цикле

Батенька, да вы извращенец. В реалтайме цикл гонять?

И какие нифиг процедуры в С++?


--------------------
Теперь при чем :P
PM   Вверх
Dreamer_0x01
Дата 12.9.2005, 14:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: нет
Всего: 12



может я не очень въехал в тему.

1. писать свой цикл обработки сообщений
2. есть достаточно эффектный путь, который с успехом применяется в Яве - там есть такая фича, как интерфейсы. Говорят, что в С++ аналогичная штука делается с помощью множественного наследования. Щас может быть соображу, как ;)


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Denn
Дата 12.9.2005, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 143
Регистрация: 6.8.2005

Репутация: нет
Всего: 2



Цитата(Dreamer_0x01 @ 12.9.2005, 14:26)
Говорят, что в С++ аналогичная штука делается с помощью множественного наследования. Щас может быть соображу, как ;)

Шаблон Command называется.
PM MAIL ICQ   Вверх
Kurt
Дата 12.9.2005, 20:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлеченный
***


Профиль
Группа: Участник Клуба
Сообщений: 1662
Регистрация: 22.8.2003
Где: Краснодар

Репутация: нет
Всего: 36



Dreamer_0x01
Если покажешь пример - буду очень благодарен..

[offtop]
Н-да.. Надо подтянуть свои знания в C++.. smile
[/offtop]


--------------------
Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед)
...
Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн)
PM ICQ   Вверх
oleg1973
Дата 13.9.2005, 01:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


asm fanat
****


Профиль
Группа: Экс. модератор
Сообщений: 3283
Регистрация: 16.7.2003
Где: Italy

Репутация: 1
Всего: 34



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

Ignat
ну а в чем проблема?
сначала вызову некий алгоритм который обрабатывает нажатия пимп/джойстика/мыши юсера
а потом вызову алгоритм хождения моей клетки которая получив координаты клетки юсера просчитает оптимальную траэкторию движения




--------------------
SST 465555
icq 200-512-712
PM MAIL WWW ICQ   Вверх
Kurt
Дата 13.9.2005, 02:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлеченный
***


Профиль
Группа: Участник Клуба
Сообщений: 1662
Регистрация: 22.8.2003
Где: Краснодар

Репутация: нет
Всего: 36



oleg1973
алгоритм поиска, конечно, понятен. вопрос в оптимальном организации системы - ты предлагаешь в цикле гонять процедуры проверки наступления некоторых условий? (в моем случае - премещение объекта на соседнюю клетку). А если объектов (разных) будет 10? 50? 100?

З.Ы.
Господа, обсуждение уходит в сторону. Я, собственно, ничего против не имею, но все же.. smile


--------------------
Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед)
...
Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн)
PM ICQ   Вверх
chipset
Дата 13.9.2005, 03:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4071
Регистрация: 11.1.2003
Где: Seattle, US

Репутация: 27
Всего: 165



Реализуешь указатель на функцию-член класса.
Передаешь её как обработчик события.
В случае чего оно вызываеться. Ну не события конечно в прямом понятии, но любые события сводяться к циклу или чему то такому.
Добавлено @ 03:05
А Boost не надо тянуть, имхо.


--------------------
Цитата(Jimi Hendrix)
Well, I stand up next to a mountain
And I chop it down with the edge of my hand
PM MAIL WWW   Вверх
Void
Дата 13.9.2005, 06:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Цитата(chipset @ 13.9.2005, 05:04)
Реализуешь указатель на функцию-член класса.
Передаешь её как обработчик события.

Вот только вместе с этим указателем придется передавать еще и указатель на экземпляр этого класса. Сам по себе он невызываем.

Цитата(chipset @ 13.9.2005, 05:04)
А Boost не надо тянуть, имхо.

Предлагаешь писать делегаты самому? Нет, для данной задачи Boost, быть может, и overkill, но вообще не вижу ничего криминального.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
ST1
Дата 13.9.2005, 19:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 20.7.2005
Где: Уфа

Репутация: нет
Всего: 1



@Kurt
Возможно вас заинтересует эта информация:
1) http://is.ifmo.ru/projects/loderunner/ -- реализация Lode Runner (Java)
2) http://www.softcraft.ru/forum/viewtopic.php?t=216 -- реализация активных объектов на C++
PM MAIL WWW ICQ   Вверх
Kurt
Дата 9.11.2005, 23:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлеченный
***


Профиль
Группа: Участник Клуба
Сообщений: 1662
Регистрация: 22.8.2003
Где: Краснодар

Репутация: нет
Всего: 36



Хех, опять прихожу к событиям. (отдельный проджект)
Народ, кто-нибудь реализовывал систему событий на основе GLib? Может, примерчик какой подкинете? А то у меня только reference по функциям. smile
..
Просто сам проект на GTK - не хочется тянуть ничего лишнего. Тем более, в манах по GTK рекомендуют именно GLib...


--------------------
Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед)
...
Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн)
PM ICQ   Вверх
Neitron
Дата 10.11.2005, 10:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 580
Регистрация: 3.10.2005
Где: Москва

Репутация: 2
Всего: 5



Цитата(Ignat @ 12.9.2005, 12:41)
Цитата(oleg1973 @ 12.9.2005, 11:09)
гонять их в цикле

Батенька, да вы извращенец. В реалтайме цикл гонять?

И какие нифиг процедуры в С++?

Батенька а ты когда-нибудь на АПИ программировал и ловил сообщения?
Я не понимаю, чем вам не нравится создания события на основе сообщений Винды.


--------------------
Хороший программист никогда ничего не делает хорошо с первого раза. Он понимает важность патчей.
Ⓘ ⓁⒾⓀⒺ ⓂⓄⓏⒾⓁⓁⒶ
PM MAIL   Вверх
Ignat
Дата 10.11.2005, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Флудератор
****


Профиль
Группа: Экс. модератор
Сообщений: 4030
Регистрация: 19.4.2004
Где: غيليندزيك مدينة

Репутация: 3
Всего: 73



Цитата(Neitron @ 10.11.2005, 10:28)
Батенька а ты когда-нибудь на АПИ программировал и ловил сообщения?

Не далее как вчера smile
Добавлено @ 13:50
Кстати, а на каком именно АПИ? Или кроме ВыньАПИ других не существует?


--------------------
Теперь при чем :P
PM   Вверх
Neitron
Дата 10.11.2005, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 580
Регистрация: 3.10.2005
Где: Москва

Репутация: 2
Всего: 5



Ignat
Это типо тест на сообразительность?
На моём АПИ моей программы smile

Это сообщение отредактировал(а) Neitron - 10.11.2005, 14:27


--------------------
Хороший программист никогда ничего не делает хорошо с первого раза. Он понимает важность патчей.
Ⓘ ⓁⒾⓀⒺ ⓂⓄⓏⒾⓁⓁⒶ
PM MAIL   Вверх
Ignat
Дата 10.11.2005, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Флудератор
****


Профиль
Группа: Экс. модератор
Сообщений: 4030
Регистрация: 19.4.2004
Где: غيليندزيك مدينة

Репутация: 3
Всего: 73



Цитата(Neitron @ 10.11.2005, 14:23)
На моём АПИ моей программы

Просто нигде не сказано, что прогрмма для винды. Она может быть и для юникса. smile


--------------------
Теперь при чем :P
PM   Вверх
powerfox
Дата 11.11.2005, 15:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


I wanna fork()
****


Профиль
Группа: Комодератор
Сообщений: 3990
Регистрация: 1.10.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 97



Можно использавать Qt.
Сейчас пишу змейку - использую SDL, там есть возможность отлавливать клавиши:

Код

while(done == 0){ 
        SDL_Event event; 
        while ( SDL_PollEvent(&event) ){ 
            if ( event.type == SDL_QUIT ){ done = 1; } 
            if ( event.type == SDL_KEYDOWN ){
                if ( event.key.keysym.sym == SDLK_ESCAPE ){ done = 1; } 
           } 
      }
        keys = SDL_GetKeyState(NULL);


Всё это гоняется в цикле. Правда, я пока только изучаю С++. а из Qt знаю только "Hello, Qt!" smile


--------------------
user posted image
PM WWW   Вверх
Kurt
Дата 11.11.2005, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлеченный
***


Профиль
Группа: Участник Клуба
Сообщений: 1662
Регистрация: 22.8.2003
Где: Краснодар

Репутация: нет
Всего: 36



У меня GTK-приложение.
Определены два пользовательских класса.
Задача - при изменении состояния объекта первого класса определенным образом должно среагировать некоторое множество объектов второго класса.
Все. Больше ничего. Мне нужно то же самое, что происходит в любой GTK/QT/WxWindows-программе! Есть класс, есть событие (определенное в этом класса), нужно повесить на него обработчик.
Программа фактически кроссплатформенная - компилится и под Linux и под Windows. И вообще под все, где есть С++ и GTK. Поэтому очень не хочется заморачиваться с этими всеми системными сообщениями и т.п.
Тянуть дополнительные либы тоже жаба душит - и так уже от GTK неплохо зависим. А под зависимостью от GTK я понимаю зависимость еще и от glib, atk, pango и т.п. и т.д.
Господа, я в растерянности. Работа стоит, а время идет. smile


--------------------
Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед)
...
Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн)
PM ICQ   Вверх
Дмитрий Т
Дата 11.11.2005, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 16.3.2005
Где: Самара

Репутация: 4
Всего: 4



Цитата(Kurt @ 11.11.2005, 23:11)
Господа, я в растерянности. Работа стоит, а время идет. smile

Всё правильно сказали про указатель на функцию.

Вот пример:

Класс порождающий событие
Код

    class StrFinder;
    
    // type of event
    typedef void (*ShowResult_t) (const std::string& CurWord);

    // main class
    class StrFinder{
        std::string CurWord;
        ShowResult_t ShowResult;
        inline void doShowResult();
    public:
        void SetShowResult (ShowResult_t value);
    };

inline void StrFinder::doShowResult() 
{
    if (ShowResult) {
        ShowResult(CurWord);
    }
}

void StrFinder::SetShowResult (ShowResult_t value) 
{
    ShowResult = value;
}


У реагирующего на событие:
Код

void ShowResult (const std::string& CurWord)
{
    std::cout << CurWord << std::endl;
}


теперь связываем:
Код

f = new StrFinder();
f->SetShowResult(ShowResult);


Этот код - неопробованные вырезки из рабочей программы.

Этот вариант хорош для одного реагирующего на событие, но прост и очень часто встречается. Для нескольких реагирующих надо менять SetShowResult и хранить массив указателей или лучше воспользоваться другой схемой. Кратко почитать о разных схемах работы с событиями в С++ можно на http://www.fox-toolkit.org/faq.html в вопросе "Why did FOX choose the message-map based callback paradigm" (нашёл когда выбирал библиотеку).

PM MAIL WWW ICQ Skype   Вверх
Kurt
Дата 12.11.2005, 00:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлеченный
***


Профиль
Группа: Участник Клуба
Сообщений: 1662
Регистрация: 22.8.2003
Где: Краснодар

Репутация: нет
Всего: 36



Благодарю за ответ.
С твоим примером все стало намного проще. Правда, у меня несколько реагирующих объектов, но это я уже решу... надеюсь. smile

З.Ы. Ну, не спец я в С++, что тут поделаешь? smile


--------------------
Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед)
...
Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн)
PM ICQ   Вверх
S.A.P.
Дата 12.11.2005, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2664
Регистрация: 11.6.2004

Репутация: 9
Всего: 71



Вот мой небольшой велосипед с несколькими реагирующими объектами.
Код

using namespace std;

typedef void (*Slot)();

class Signal {
public:
    vector<Slot> slots;
    void operator()();
    Signal& operator <= ( Slot );
};

void Signal::operator()()
{
    vector<Slot>::iterator it;
    for ( it = slots.begin(); it != slots.end(); it++ ) 
        (*it)();
}

Signal& Signal::operator <= ( Slot slot )
{
    slots.push_back( slot );
    return *this;
}


Юзать можно так.

Код

using namespace std;

void slot1()
{
    cout << "slot1" << endl;
}

void slot2()
{
    cout << "slot2" << endl;
}

void slot3()
{
    cout << "slot3" << endl;
}

int main(int argc, char *argv[])
{
    Signal signal;
    signal <= slot2 <= slot3 <= slot1;
    signal();
    system("PAUSE");
    return EXIT_SUCCESS;
}

вывод:
Цитата

slot2
slot3
slot1


Добавлено @ 21:43
Помидоров не жду smile .
PM MAIL   Вверх
libricon
Дата 12.11.2005, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 2.10.2005
Где: estonia, tallinn

Репутация: нет
Всего: нет



хорошая мысть qt
тама реализована система signal - slot
т.е появился сигнал, вызвался слот .
пример
connect ( что ,SIGNAL(событие),кому,SLOT(че сделать));

или чтото похожее


PM MAIL ICQ Skype MSN   Вверх
Kurt
Дата 12.11.2005, 23:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлеченный
***


Профиль
Группа: Участник Клуба
Сообщений: 1662
Регистрация: 22.8.2003
Где: Краснодар

Репутация: нет
Всего: 36



Perchilla
Благодарю. Сейчас попробую применить. smile

libricon
Не спорю, в QT все классно сделали, но, увы, я работаю с GTK.


--------------------
Для корабля, который не знает куда плыть, нет попутного ветра... ((С) Архимед)
...
Все знают, что это невозможно. Но случайно находится невежда, который этого не знает. Он-то и делает открытие.. ((С) А. Эйнштейн)
PM ICQ   Вверх
powerfox
Дата 13.11.2005, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


I wanna fork()
****


Профиль
Группа: Комодератор
Сообщений: 3990
Регистрация: 1.10.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 97



To Perchilla:
Не могли бы Вы дать пояснения к коду?


--------------------
user posted image
PM WWW   Вверх
S.A.P.
Дата 13.11.2005, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2664
Регистрация: 11.6.2004

Репутация: 9
Всего: 71



Цитата(powerfox @ 13.11.2005, 14:16)
To Perchilla:
Не могли бы Вы дать пояснения к коду?

тут я просто создал объект функцию (сигнал) с перегруженным оператором (), к которому можно подключать другие функции (слоты). Для подключения слотов я перегрузил оператор <= (для наглядности). Указатели на слоты храняться в контейнере std::vector. При имитировании сигнала ( signal() ) соответственно вызываются все слоты, которые былы подключены. То есть как в QT, например при нажатии на QPushButton имитируется сигнал clicked().

Но мой пример не очень хорош, чаще требуется передавать какие - то параметры из сигнала в слоты ( например координаты, как у Kurt ). Для частного случая можно и напильником подогнать, но если в одном классе надо держать несколько сигналов с разныи количеством параметров, то лучше написать шаблон. Вот только в шаблонах я пока плаваю smile и не могу понять как правильно это сделать: перегрузить шаблоны для разного количества параметров или можно как то хитро обойти одним шаблоном.

Еще бы не мешало предотвращать попытки повторного подключения слота, дать возможность отключение определенного слота, сделать, чтобы сигнал мог возвращать значения... Но все это больше похоже на переписывание boost::signals.

А вот интересно, как в boost сделали передачу параметров в слоты. Знаю, что в QT это реализовано на уровне препроцессора, что немного огорчает smile .
PM MAIL   Вверх
Дмитрий Т
Дата 13.11.2005, 20:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 16.3.2005
Где: Самара

Репутация: 4
Всего: 4



Цитата(Kurt @ 13.11.2005, 00:59)
Не спорю, в QT все классно сделали, но, увы, я работаю с GTK.

Кстати, как помню, на qt-шном сайте видел обсуждение по поводу событий, что ради совместимости со старыми наработками разработчики отказываются заменить систему на более эффективную... А на www.fox-toolkit.org утверждается, что в FOX самая лучшая система событий, но я лично не анализировал (по другим причинам выбрал WxWidgets).
PM MAIL WWW ICQ Skype   Вверх
Дмитрий Т
Дата 13.11.2005, 21:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 16.3.2005
Где: Самара

Репутация: 4
Всего: 4



Цитата(Perchilla @ 13.11.2005, 16:17)
... но если в одном классе надо держать несколько сигналов с разныи количеством параметров, то лучше написать шаблон. Вот только в шаблонах я пока плаваю  smile и не могу понять как правильно это сделать: перегрузить шаблоны для разного количества параметров или можно как то хитро обойти одним шаблоном.


Может не шаблон, а несколько классов?
Посмотри раздел Events на
http://wxwidgets.org/manuals/2.6.2/wx_clas...ml#classesbycat
у этой достаточно старой и распространённой библиотеки есть иерархия типов событий...
PM MAIL WWW ICQ Skype   Вверх
S.A.P.
Дата 14.11.2005, 08:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2664
Регистрация: 11.6.2004

Репутация: 9
Всего: 71



Цитата
Может не шаблон, а несколько классов?

просто все мои представления об этом отталкиваются от boost::signals, а там можно так записать:
Код

void print_sum(float x, float y)
{
  std::cout << "The sum is " << x+y << std::endl;
}

void print_product(float x, float y)
{
  std::cout << "The product is " << x*y << std::endl;
}

void print_difference(float x, float y)
{
  std::cout << "The difference is " << x-y << std::endl;
}

void print_quotient(float x, float y)
{
  std::cout << "The quotient is " << x/y << std::endl;
}

// . . . 

boost::signal<void (float, float)> sig;

sig.connect(&print_sum);
sig.connect(&print_product);
sig.connect(&print_difference);
sig.connect(&print_quotient);

sig(5, 3);

PM MAIL   Вверх
srd
Дата 14.11.2005, 13:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


Профиль
Группа: Участник Клуба
Сообщений: 951
Регистрация: 30.8.2003
Где: Владивосток

Репутация: 27
Всего: 49



Цитата
А на www.fox-toolkit.org утверждается, что в FOX самая лучшая система событий, но я лично не анализировал (по другим причинам выбрал WxWidgets).

В FOX Toolkit такое же мракобесие на макросах, как в wxWidgets или MFC.


--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
Guest
Дата 15.11.2005, 14:51 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Цитата(Perchilla @ 14.11.2005, 08:20)
Цитата
Может не шаблон, а несколько классов?

просто все мои представления об этом отталкиваются от boost::signals, а там можно так записать:
Код

void print_sum(float x, float y)
{
  std::cout << "The sum is " << x+y << std::endl;
}

void print_product(float x, float y)
{
  std::cout << "The product is " << x*y << std::endl;
}

void print_difference(float x, float y)
{
  std::cout << "The difference is " << x-y << std::endl;
}

void print_quotient(float x, float y)
{
  std::cout << "The quotient is " << x/y << std::endl;
}

// . . . 

boost::signal<void (float, float)> sig;

sig.connect(&print_sum);
sig.connect(&print_product);
sig.connect(&print_difference);
sig.connect(&print_quotient);

sig(5, 3);

А где здесь события с разным количеством аргументов? Вроде тоже самое только тип задаётся с помошью шаблона.
  Вверх
S.A.P.
Дата 15.11.2005, 17:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2664
Регистрация: 11.6.2004

Репутация: 9
Всего: 71



Цитата(Guest @ 15.11.2005, 14:51)
А где здесь события с разным количеством аргументов? Вроде тоже самое только тип задаётся с помошью шаблона.
разница в том, что я юзая один класс могу создать сигналы с разлиным количеством параметров. Количество параметров у слотов разумеется должно быть одинаково. Правда в QT это не обязательно, но это другая тема.

PM MAIL   Вверх
nikf
Дата 15.11.2005, 20:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 6.6.2005
Где: город-герой Жирно вск

Репутация: нет
Всего: 1



делегаты в .net не более чем функции обратного вызова в си. а нагородили-то на три страницы...QT приплели...

Это сообщение отредактировал(а) nikf - 15.11.2005, 20:58
PM MAIL   Вверх
Void
Дата 15.11.2005, 21:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Цитата(nikf @ 15.11.2005, 22:57)
делегаты в .net не более чем функции обратного вызова в си.

Для Си все просто. А вот для C++ аналогом делегатов дотнета является boost::function + bind'еры. Потому что метод объекта сам по себе не является вызываемой сущностью.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
nikf
Дата 15.11.2005, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 127
Регистрация: 6.6.2005
Где: город-герой Жирно вск

Репутация: нет
Всего: 1



Цитата(Void @ 15.11.2005, 21:04)
А вот для C++ аналогом делегатов дотнета является boost
boost это библиотека, а не язык, вопрос про язык был, а библиотек всяких разных в том числе и boost достаточно много. от этого они не становятся стандартом языка

PM MAIL   Вверх
Void
Дата 15.11.2005, 21:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



nikf
Хорошо. Аналогом делегатов дотнета является boost::function или близкая по функциональности библиотека. Так устраивает? В C++ нет примитивов, позволяющих решить поставленную задачу.
Цитата(nikf @ 15.11.2005, 23:37)
от этого они не становятся стандартом языка

Почти стали. Посмотри TR1 по стандартной библиотеке.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
mes
Дата 18.3.2008, 17:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Иногда удобно применять подход описанный ниже. Как называется не знаю. Но цель вынести обшую функционалость в обший класс обработчик.
Состоит из трех частей : 
1 определение типов сообшений,так чтоб их объект содержал нужную информацию о событии - например в описанной ниже хранится координаты покинутой клетки и той на которую перепрыгнул объект
2. Интерфейс обработчика сообшений - состоид из двух частей
а. перегруженный метод (в примере OnEvt) для диспатчеризации нужного типа нужному обработчику
б. виртуальный метод  - обработчик события 
3. сам объект

Преимушества :
1. Типизация которая не даст допустить ошибку.
2..  двойная диспетчиризация, что позволяет раздельно развивать, но совместно использовать  сами обьекты и лабиринты.
3.  логика обработки событий сгруппированна в одном месте. 
4.  информация собирается в момент происхождения события а не в момент обработки
6.  *..
Недостатки:
1. нужна проектировка классов (что в принципе желательно при любом подходе)
2. естественно не потокобезопасная
3 *..
 *..  = может есть что то еше - сейчас не пришло в голову 


Код

namespace Evt {
struct SObjectMoved 
{
  SObjectMoved (SCoord oldcell, newcell) :oldCell (oldcell), newCell (oldCell)
  SCoord  oldCell;
  SCoord newCell;
}
};

class GameObject {...}; // то что движется по лабиринту

class LabirintEvt
{
   public :  
     void OnEvt (const Evt::SObjectMoved& evt,   GameObject* pobj) { doOnObjectMovedEvt(evt,pobj); };  // перегрузка функций для разных событий
     void OnEvt (...)
  protected: 
     void doOnObjectMovedEvt (const Evt::SObjectMoved& evt,   GameObject* pobj) =0;
}

class Pacman : public GameObject {..}  *pPacman;
//где внутри цикла
if (pEvt) pEvt->OnEvt (Evt::SObjectMoved(SCooord(2,1),SCooord(2,2)), pPacman )





--------------------
PM MAIL WWW   Вверх
Дмитрий Т
Дата 19.3.2008, 09:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 16.3.2005
Где: Самара

Репутация: 4
Всего: 4



Цитата(mes @ 18.3.2008,  18:41)
Иногда удобно применять подход описанный ниже. Как называется не знаю. Но цель вынести обшую функционалость в обший класс обработчик.
[/code]

Насколько понял, вы просто вынесли код события в отдельное дерево классов начинающееся с LabirintEvt. Не совсем понятно когда такой подход удобен... Если есть объект Лабиринт и объект Человечек, то для рекции Лабиринта на движения Человечка достаточно в одном классе создать указатель на функцию...
PM MAIL WWW ICQ Skype   Вверх
mes
Дата 19.3.2008, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Дмитрий Т @  19.3.2008,  09:55 Найти цитируемый пост)
Не совсем понятно когда такой подход удобен

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

Цитата(Дмитрий Т @  19.3.2008,  09:55 Найти цитируемый пост)
для рекции Лабиринта на движения Человечка

вобше сообшения предназначены не столько для реакции Лабиринта на движения Человечка   
сколько для реакции "внешних" компонентов на взаимоотношение между Человечком и Лабиринтом.


Пример: Главное окно разбито на несколько компонентов . В одном отображен сам процесс игры, в других информация о игре: координаты объекта , список ходов и т.д.

Код


template <class T>
class TCluster 
{
typedef std::set<T> TEvtSet;
public:
template <class P> void OnEvt (P p1) { for (TEvtSet::iterator it = m_set.begin(); it!=m_set.end(); ++it) { if (*it)  (*it)->OnEvt(p1); }  
.. //здесь для двух и более параметров
void insert (T pevt) {m_set.insert(pevt); }
void erase (T pevt) {m_set.erase(pevt); }
private:
TEvtSet m_set;

};

class CGame
{
public:
 void MoveGameObject (int id, SCoord coord) { if (doMove(...)==success) m_LabirintEvtCluster.OnEvt (SObjectMoved (... ); } // множественная рассылка
void insert (ILabirintEvt * pEvt) {m_LabirintEvtCluster.insert (pEvt); }
void erase (ILabirintEvt * pEvt) {m_LabirintEvtCluster.erase (pEvt); }
private:
     TCluster<ILabirintEvt> m_LabirintEvtCluster;
...
};

class WGamePanel // образец визуального компонента
                                     : public WPanel , protected ILabirintEvt // двойное наследие для упрошения при использовании одного контролера на виджет
{
public:
           WActionScene (WWindow *parent, ..., CGame *pgame) { pgame ->insert((ILabirintEvt*)this); } 
            virtual ~WActionScene (WWindow *parent, ..., CGame *pgame) { pgame ->erase((ILabirintEvt*)this); }
 protected: 
        doOn...Evt ... { }
      ..
}; 
class WActionScene : ... // окно процесса игры 
class WHistory:              // панель с показом ходов
class WCoord :           // текушее положение
..                                  // что нибудь еше

class CStatusBarCtrl: protected ILabirintEvt  // классическое применение контролера событий
{
public:
    CStatusBarCtrl(WStatusBar* pbar, CGame *pgame) : p_bar(pbar) { pgame->insert (this); }
...
private:
WSatatusBar *p_bar;
};

class WMainFame : WFrame  // главное окно
{
public:
...

protected:
  void CreateContols () {  new WActionScene (this,..., &m_Game); // создание компонента на главном окне с получением событием от лабиринта
                                             WPanel *  pwPanel = new WPanel (this) ;// к примеру боковая панель 
                                             new WHistory (pwPanel,..., &m_Game); //создание компонента на боковой панели, но он все так же будет получать сообшения                                 
                                             pStBarCtrl = newCStatusBarCtrl(this->GetStatusBar(), &m_Game);
                                        };
private:
     CGame m_Game;
      CStatusBarCtrl * pStBarCtrl;
};

};


* Пример привел в обшей схеме с упрошениями для легкого представления.. 
названия выбраны условн, приставка W - означает виджет.
Преимушество приведенного примера : реализация визуализации отделена от реализации логики игры.
 



Это сообщение отредактировал(а) mes - 19.3.2008, 15:17


--------------------
PM MAIL WWW   Вверх
Дмитрий Т
Дата 21.3.2008, 10:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 16.3.2005
Где: Самара

Репутация: 4
Всего: 4



А здесь не тоже самое http://docs.wxwidgets.org/stable/wx_classe...ml#classesbycat дерево начинающееся с Events?
PM MAIL WWW ICQ Skype   Вверх
mes
Дата 21.3.2008, 15:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Дмитрий Т @  21.3.2008,  10:40 Найти цитируемый пост)
А здесь не тоже самое http://docs.wxwidgets.org/stable/wx_classe...ml#classesbycat дерево начинающееся с Events? 


Все реализации событий похожи  друг на друга. Однако в зависимости от ситуации отдаешь предпочтение одному (или смеси) из этих способов.
В приведенном выше примере во первых присутствует независимость от библиотек, что позволяет сделать логику модели программы независимой 
от применения ГУИ-библиотеки. Во вторых вышеприведенный пример осушествляет прямую диспетчиризацию (что является иногда недостатком, а иногда преимушеством - в зависимости от исполняемой задачи )




--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0989 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.