| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Есть ли события в С++?.. |
| Автор: Kurt 11.9.2005, 18:19 |
| Блуждая в поисках работы (ну не везет мне пока! Первоначально просили сделать на С++, но в итоге сошлись на C#. ( Задание сделал и отправил. Теперь вот думаю, как бы я решил эту задачу на С++. Подскажите, пожалуйста, есть ли в С++ что-то подобное событиям? То есть мне надо чтобы один объект при наступлении некоторых условий генерировал событие, а другой - реагировал на него. Если можете показать пример, как это сделать - вообще здорово.. |
| Автор: srd 11.9.2005, 19:47 |
| Существуют разные реализации схемы сигнал/слот. Например, boost::signals или libsigc++ |
| Автор: Void 11.9.2005, 19:59 | ||||
Пример кода с использованием Boost.Signals и Boost.Bind:
Вывод:
|
| Автор: chipset 12.9.2005, 03:45 |
| Исключения можешь бросать и ловить другими классами. А вообще просто закидываешь делегат и вызываешь при необходимости (вариант лучше) |
| Автор: Void 12.9.2005, 06:31 | ||
Это как (в контексте задачи)? |
| Автор: chipset 12.9.2005, 07:34 | ||
Перечитал, понял - в контексте задачи никак, да и не красиво это, в общем |
| Автор: Guest 12.9.2005, 08:47 |
| Это можно и без boost делаеть . См паттерн Chain of Responsibility. Но в вашем случае всего то два объекта, один из которых генерит запрос, другой обрабатывает. Это вообще элементарно |
| Автор: oleg1973 12.9.2005, 10:09 |
| чет вы перемудрили слишком что мешает сделать 2 процедуры - первая для "ручного" обьекта а вторая для автоматического и гонять их в цикле? какие нафиг события? п.с. куда катится мир? |
| Автор: Ignat 12.9.2005, 12:41 | ||
Батенька, да вы извращенец. В реалтайме цикл гонять? И какие нифиг процедуры в С++? |
| Автор: Dreamer_0x01 12.9.2005, 14:26 |
| может я не очень въехал в тему. 1. писать свой цикл обработки сообщений 2. есть достаточно эффектный путь, который с успехом применяется в Яве - там есть такая фича, как интерфейсы. Говорят, что в С++ аналогичная штука делается с помощью множественного наследования. Щас может быть соображу, как ;) |
| Автор: Denn 12.9.2005, 14:51 | ||
Шаблон Command называется. |
| Автор: Kurt 12.9.2005, 20:05 |
| Dreamer_0x01 Если покажешь пример - буду очень благодарен.. [offtop] Н-да.. Надо подтянуть свои знания в C++.. [/offtop] |
| Автор: oleg1973 13.9.2005, 01:59 |
| мамамиииия какой маразм, люди вы бредите и так представим некое поле в виде клеточек по которому бродят 2 фигуры (размером в клетку) на даном поле есть некоторые клетки которые нельзя пройти (стены блин) так как шаг фигуры равен размеру клетки , то вообшем я не вижу проблем для реализации алгоритма Ignat ну а в чем проблема? сначала вызову некий алгоритм который обрабатывает нажатия пимп/джойстика/мыши юсера а потом вызову алгоритм хождения моей клетки которая получив координаты клетки юсера просчитает оптимальную траэкторию движения |
| Автор: Kurt 13.9.2005, 02:15 |
| oleg1973 алгоритм поиска, конечно, понятен. вопрос в оптимальном организации системы - ты предлагаешь в цикле гонять процедуры проверки наступления некоторых условий? (в моем случае - премещение объекта на соседнюю клетку). А если объектов (разных) будет 10? 50? 100? З.Ы. Господа, обсуждение уходит в сторону. Я, собственно, ничего против не имею, но все же.. |
| Автор: chipset 13.9.2005, 03:04 |
| Реализуешь указатель на функцию-член класса. Передаешь её как обработчик события. В случае чего оно вызываеться. Ну не события конечно в прямом понятии, но любые события сводяться к циклу или чему то такому. Добавлено @ 03:05 А Boost не надо тянуть, имхо. |
| Автор: Void 13.9.2005, 06:30 | ||||
Вот только вместе с этим указателем придется передавать еще и указатель на экземпляр этого класса. Сам по себе он невызываем.
Предлагаешь писать делегаты самому? Нет, для данной задачи Boost, быть может, и overkill, но вообще не вижу ничего криминального. |
| Автор: ST1 13.9.2005, 19:01 |
| @Kurt Возможно вас заинтересует эта информация: 1) http://is.ifmo.ru/projects/loderunner/ -- реализация Lode Runner (Java) 2) http://www.softcraft.ru/forum/viewtopic.php?t=216 -- реализация активных объектов на C++ |
| Автор: Kurt 9.11.2005, 23:57 |
| Хех, опять прихожу к событиям. (отдельный проджект) Народ, кто-нибудь реализовывал систему событий на основе GLib? Может, примерчик какой подкинете? А то у меня только reference по функциям. .. Просто сам проект на GTK - не хочется тянуть ничего лишнего. Тем более, в манах по GTK рекомендуют именно GLib... |
| Автор: Neitron 10.11.2005, 10:28 | ||||
Батенька а ты когда-нибудь на АПИ программировал и ловил сообщения? Я не понимаю, чем вам не нравится создания события на основе сообщений Винды. |
| Автор: Ignat 10.11.2005, 13:49 | ||
Не далее как вчера Добавлено @ 13:50 Кстати, а на каком именно АПИ? Или кроме ВыньАПИ других не существует? |
| Автор: Neitron 10.11.2005, 14:23 |
| Ignat Это типо тест на сообразительность? На моём АПИ моей программы |
| Автор: Ignat 10.11.2005, 14:29 | ||
Просто нигде не сказано, что прогрмма для винды. Она может быть и для юникса. |
| Автор: powerfox 11.11.2005, 15:10 | ||
| Можно использавать Qt. Сейчас пишу змейку - использую SDL, там есть возможность отлавливать клавиши:
Всё это гоняется в цикле. Правда, я пока только изучаю С++. а из Qt знаю только "Hello, Qt!" |
| Автор: Kurt 11.11.2005, 22:11 |
| У меня GTK-приложение. Определены два пользовательских класса. Задача - при изменении состояния объекта первого класса определенным образом должно среагировать некоторое множество объектов второго класса. Все. Больше ничего. Мне нужно то же самое, что происходит в любой GTK/QT/WxWindows-программе! Есть класс, есть событие (определенное в этом класса), нужно повесить на него обработчик. Программа фактически кроссплатформенная - компилится и под Linux и под Windows. И вообще под все, где есть С++ и GTK. Поэтому очень не хочется заморачиваться с этими всеми системными сообщениями и т.п. Тянуть дополнительные либы тоже жаба душит - и так уже от GTK неплохо зависим. А под зависимостью от GTK я понимаю зависимость еще и от glib, atk, pango и т.п. и т.д. Господа, я в растерянности. Работа стоит, а время идет. |
| Автор: Дмитрий Т 11.11.2005, 23:41 | ||||||||
Всё правильно сказали про указатель на функцию. Вот пример: Класс порождающий событие
У реагирующего на событие:
теперь связываем:
Этот код - неопробованные вырезки из рабочей программы. Этот вариант хорош для одного реагирующего на событие, но прост и очень часто встречается. Для нескольких реагирующих надо менять SetShowResult и хранить массив указателей или лучше воспользоваться другой схемой. Кратко почитать о разных схемах работы с событиями в С++ можно на http://www.fox-toolkit.org/faq.html в вопросе "Why did FOX choose the message-map based callback paradigm" (нашёл когда выбирал библиотеку). |
| Автор: Kurt 12.11.2005, 00:27 |
| Благодарю за ответ. С твоим примером все стало намного проще. Правда, у меня несколько реагирующих объектов, но это я уже решу... надеюсь. З.Ы. Ну, не спец я в С++, что тут поделаешь? |
| Автор: S.A.P. 12.11.2005, 21:42 | ||||||
Вот мой небольшой велосипед с несколькими реагирующими объектами.
Юзать можно так.
вывод:
Добавлено @ 21:43 Помидоров не жду |
| Автор: libricon 12.11.2005, 22:03 |
| хорошая мысть qt тама реализована система signal - slot т.е появился сигнал, вызвался слот . пример connect ( что ,SIGNAL(событие),кому,SLOT(че сделать)); или чтото похожее |
| Автор: Kurt 12.11.2005, 23:59 |
| Perchilla Благодарю. Сейчас попробую применить. libricon Не спорю, в QT все классно сделали, но, увы, я работаю с GTK. |
| Автор: powerfox 13.11.2005, 14:16 |
| To Perchilla: Не могли бы Вы дать пояснения к коду? |
| Автор: S.A.P. 13.11.2005, 15:17 | ||
тут я просто создал объект функцию (сигнал) с перегруженным оператором (), к которому можно подключать другие функции (слоты). Для подключения слотов я перегрузил оператор <= (для наглядности). Указатели на слоты храняться в контейнере std::vector. При имитировании сигнала ( signal() ) соответственно вызываются все слоты, которые былы подключены. То есть как в QT, например при нажатии на QPushButton имитируется сигнал clicked(). Но мой пример не очень хорош, чаще требуется передавать какие - то параметры из сигнала в слоты ( например координаты, как у Kurt ). Для частного случая можно и напильником подогнать, но если в одном классе надо держать несколько сигналов с разныи количеством параметров, то лучше написать шаблон. Вот только в шаблонах я пока плаваю Еще бы не мешало предотвращать попытки повторного подключения слота, дать возможность отключение определенного слота, сделать, чтобы сигнал мог возвращать значения... Но все это больше похоже на переписывание boost::signals. А вот интересно, как в boost сделали передачу параметров в слоты. Знаю, что в QT это реализовано на уровне препроцессора, что немного огорчает |
| Автор: Дмитрий Т 13.11.2005, 20:44 | ||
Кстати, как помню, на qt-шном сайте видел обсуждение по поводу событий, что ради совместимости со старыми наработками разработчики отказываются заменить систему на более эффективную... А на www.fox-toolkit.org утверждается, что в FOX самая лучшая система событий, но я лично не анализировал (по другим причинам выбрал WxWidgets). |
| Автор: Дмитрий Т 13.11.2005, 21:00 | ||
Может не шаблон, а несколько классов? Посмотри раздел Events на http://wxwidgets.org/manuals/2.6.2/wx_classesbycat.html#classesbycat у этой достаточно старой и распространённой библиотеки есть иерархия типов событий... |
| Автор: S.A.P. 14.11.2005, 08:20 | ||||
просто все мои представления об этом отталкиваются от boost::signals, а там можно так записать:
|
| Автор: srd 14.11.2005, 13:05 | ||
В FOX Toolkit такое же мракобесие на макросах, как в wxWidgets или MFC. |
| Автор: Guest 15.11.2005, 14:51 | ||||||
А где здесь события с разным количеством аргументов? Вроде тоже самое только тип задаётся с помошью шаблона. |
| Автор: S.A.P. 15.11.2005, 17:05 | ||
|
| Автор: nikf 15.11.2005, 20:57 |
| делегаты в .net не более чем функции обратного вызова в си. а нагородили-то на три страницы...QT приплели... |
| Автор: Void 15.11.2005, 21:04 | ||
Для Си все просто. А вот для C++ аналогом делегатов дотнета является boost::function + bind'еры. Потому что метод объекта сам по себе не является вызываемой сущностью. |
| Автор: nikf 15.11.2005, 21:37 | ||
|
| Автор: Void 15.11.2005, 21:45 | ||
| nikf Хорошо. Аналогом делегатов дотнета является boost::function или близкая по функциональности библиотека. Так устраивает? В C++ нет примитивов, позволяющих решить поставленную задачу.
Почти стали. Посмотри TR1 по стандартной библиотеке. |
| Автор: mes 18.3.2008, 17:41 | ||
| Иногда удобно применять подход описанный ниже. Как называется не знаю. Но цель вынести обшую функционалость в обший класс обработчик. Состоит из трех частей : 1 определение типов сообшений,так чтоб их объект содержал нужную информацию о событии - например в описанной ниже хранится координаты покинутой клетки и той на которую перепрыгнул объект 2. Интерфейс обработчика сообшений - состоид из двух частей а. перегруженный метод (в примере OnEvt) для диспатчеризации нужного типа нужному обработчику б. виртуальный метод - обработчик события 3. сам объект Преимушества : 1. Типизация которая не даст допустить ошибку. 2.. двойная диспетчиризация, что позволяет раздельно развивать, но совместно использовать сами обьекты и лабиринты. 3. логика обработки событий сгруппированна в одном месте. 4. информация собирается в момент происхождения события а не в момент обработки 6. *.. Недостатки: 1. нужна проектировка классов (что в принципе желательно при любом подходе) 2. естественно не потокобезопасная 3 *.. *.. = может есть что то еше - сейчас не пришло в голову
|
| Автор: Дмитрий Т 19.3.2008, 09:55 | ||
Насколько понял, вы просто вынесли код события в отдельное дерево классов начинающееся с LabirintEvt. Не совсем понятно когда такой подход удобен... Если есть объект Лабиринт и объект Человечек, то для рекции Лабиринта на движения Человечка достаточно в одном классе создать указатель на функцию... |
| Автор: mes 19.3.2008, 15:09 | ||
вышеназванный механизм удобен вместо реализации классической системы собщения тем, что диспетчиризация производится напрямую вместо сигналов тем что подключение подключение происходит сразу пучком и не надо задумываться что куда подключать. Он предоставляет обший интерфейс (со всеми вытекаюшими преимушествами и недостатками) на определеную группу событий, но выполнен с учетом возможности множественной диспетчеризации [пример ниже] вобше сообшения предназначены не столько для реакции Лабиринта на движения Человечка сколько для реакции "внешних" компонентов на взаимоотношение между Человечком и Лабиринтом. Пример: Главное окно разбито на несколько компонентов . В одном отображен сам процесс игры, в других информация о игре: координаты объекта , список ходов и т.д.
* Пример привел в обшей схеме с упрошениями для легкого представления.. названия выбраны условн, приставка W - означает виджет. Преимушество приведенного примера : реализация визуализации отделена от реализации логики игры. |
| Автор: Дмитрий Т 21.3.2008, 10:40 |
| А здесь не тоже самое http://docs.wxwidgets.org/stable/wx_classesbycat.html#classesbycat дерево начинающееся с Events? |