Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 86
1

Заменить делегаты функциями обратного вызова

14.04.2014, 14:48. Показов 2230. Ответов 26
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 public event EventHandler<EventClientArgs> OnNewClient;
        /// <summary>
        /// Обработка добавления нового клиента - процедура синхронизируется с потоком Control и вызывается событие
        /// </summary>
        /// <param name="Id">Адрес клиента</param>
        /// <param name="Name">Имя клиента</param>
        private void NewClientEvent(int Id, string Name)
        {
            /*if ((Control != null) && Control.InvokeRequired)
            {
                DelegateChangeClientEvent Ev = new DelegateChangeClientEvent(NewClientEvent);
                Control.Invoke(Ev, Id, Name);
            }
            else*/
                if (OnNewClient != null)
                    OnNewClient(this, new EventClientArgs(Id, Name));
        }
Мне надо сделать аналог на с++. с делегатами разобрался - их надо заменить функциями обратного вызова..
а вот как быть с событиями. есть ли аналог?или как то же обходятся люди ?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.04.2014, 14:48
Ответы с готовыми решениями:

Функция обратного вызова
#undef UNICODE #include &lt;windows.h&gt; #include &quot;resource.h&quot; #include &lt;iostream&gt; #include...

Стрелка в описании функции обратного вызова
#include &lt;iostream&gt; #include &lt;algorithm&gt; std::string s = &quot;hello&quot;; auto end =...

Передача функций обратного вызова как членов некоторого класса
Пытаюсь понемногу изучать OpenGL, и вот сейчас столкнулся с такой проблемой: Имеется некоторый...

Почему callback-функции называются функциями ОБРАТНОГО вызова
Доброго времени. Нуждаюсь в объяснении. Очередной вопрос в стиле «Что такое callback-функции и...

26
54 / 53 / 5
Регистрация: 14.08.2012
Сообщений: 252
14.04.2014, 20:13 2
Лучший ответ Сообщение было отмечено diplomat1129 как решение

Решение

Делается довольно несложно. Проект прилагаю.
Класс EventHandler реализует работу по подписке/отписке и вызову обработчиков события. Весь остальной код, предполагается, что пишет пользователь, и использует "библиотечный" EventHandler для определения своих событий.
Единственное ограничение: обработчики событий должны быть определены вне класса (а если им требуется доступ к внутренностям класса, то просто объявить их друзьями). Хотя, ничего плохого в этом не вижу, наоборот, код структурируется.
Вложения
Тип файла: 7z Test.7z (2.1 Кб, 13 просмотров)
1
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 86
17.04.2014, 19:22  [ТС] 3
Ошибка почему-то.когда использую ваш заголовочный файл
0
54 / 53 / 5
Регистрация: 14.08.2012
Сообщений: 252
17.04.2014, 19:25 4
Какая?
0
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 86
17.04.2014, 19:32  [ТС] 5
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
In file included from NMClient.cpp:14:0,
                 from main.cpp:1:
EventHandler.h: In member function ‘void EventHandler<EventArgs>::operator()(void*, EventArgs*):
EventHandler.h:34:8: error: need ‘typename’ before ‘std::list<void (*)(void*, EventArgs*)>::const_iterator’ because ‘std::list<void (*)(void*, EventArgs*)>’ is a dependent scope
   for (list<CallBackFunction>::const_iterator it = callBackList.cbegin(); it != callBackList.cend(); it++)
        ^
EventHandler.h:34:47: error: expected ‘;’ before ‘it’
   for (list<CallBackFunction>::const_iterator it = callBackList.cbegin(); it != callBackList.cend(); it++)
                                               ^
EventHandler.h:34:75: error: ‘it’ was not declared in this scope
   for (list<CallBackFunction>::const_iterator it = callBackList.cbegin(); it != callBackList.cend(); it++)
                                                                           ^
EventHandler.h: In member function ‘bool EventHandler<EventArgs>::operator==(int):
EventHandler.h:38:47: warning: NULL used in arithmetic [-Wpointer-arith]
  inline bool operator==(int a) { return (a == NULL) && (callBackList.size() == 0); }
                                               ^
EventHandler.h: In member function ‘bool EventHandler<EventArgs>::operator!=(int):
EventHandler.h:40:47: warning: NULL used in arithmetic [-Wpointer-arith]
  inline bool operator!=(int a) { return (a == NULL) && (callBackList.size() != 0); }
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
17.04.2014, 19:42 6
Лучший ответ Сообщение было отмечено diplomat1129 как решение

Решение

diplomat1129,
Там ошибка. Связанная с тем, что VC++ не требует наличия ключевого слова typename в этой ситуации (это объясняется отсутствием в VC++ two-phase name lookup, но это тянет на отдельную тему), хотя по стандарту оно должно быть.
В общем, надо так:
C++
1
for (typename list<CallBackFunction>::const_iterator it = callBackList.cbegin(); it != callBackList.cend(); it++)
1
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 86
17.04.2014, 19:46  [ТС] 7
C++
1
2
3
4
5
6
7
8
9
In file included from NMClient.cpp:14:0,
                 from main.cpp:1:
EventHandler.h: In member function ‘bool EventHandler<EventArgs>::operator==(int):
EventHandler.h:38:47: warning: NULL used in arithmetic [-Wpointer-arith]
  inline bool operator==(int a) { return (a == NULL) && (callBackList.size() == 0); }
                                               ^
EventHandler.h: In member function ‘bool EventHandler<EventArgs>::operator!=(int):
EventHandler.h:40:47: warning: NULL used in arithmetic [-Wpointer-arith]
  inline bool operator!=(int a) { return (a == NULL) && (callBackList.size() != 0); }
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
17.04.2014, 19:48 8
diplomat1129, Насчет этого наверное лучше у автора спросить. Но мне кажется, что можно просто заменить на ноль.
1
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 86
17.04.2014, 20:13  [ТС] 9
Начал использовать события
C++
1
2
3
4
5
6
EventHandler<EventMsgArgs> OnError;
 
    void ErrorEvent(string msg){
        if (OnError != 0)
          OnError(this, new EventMsgArgs(msg));
    }
Выдает такое
In file included from NMClient.cpp:14:0,
from main.cpp:1:
EventHandler.h: In instantiation of ‘void EventHandler<EventArgs>::operator()(void*, EventArgs*) [with EventArgs = EventMsgArgs]’:
NMClient.cpp:50:40: required from here
EventHandler.h:34:81: error: ‘class std::list<void (*)(void*, EventMsgArgs*), std::allocator<void (*)(void*, EventMsgArgs*)> >’ has no member named ‘cbegin’
for (typename list<CallBackFunction>::const_iterator it = callBackList.cbegin(); it != callBackList.cend(); it++)
^
EventHandler.h:34:87: error: ‘class std::list<void (*)(void*, EventMsgArgs*), std::allocator<void (*)(void*, EventMsgArgs*)> >’ has no member named ‘cend’
for (typename list<CallBackFunction>::const_iterator it = callBackList.cbegin(); it != callBackList.cend(); it++)

если не использовать в другом классе, а просто компилить, то компилиться без ошибок
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
17.04.2014, 20:18 10
diplomat1129, C++11 нужно, чтобы это работало. -std=c++11
0
54 / 53 / 5
Регистрация: 14.08.2012
Сообщений: 252
17.04.2014, 22:41 11
Всё это возможно из-за того, что я не учитывал особенности VC++ и C++11, т.к. первый категорически не перевариваю (из-за личных взглядов), а для второго у меня нет поддержки компилятора.
Изначально я создавал проект для этого файла как обычный Win32 без всяких там .net и clr. Среда разработки VS2010.
По поводу этих ошибок сказать трудно, что компилятору не нравится, может нет нужных зависимостей, иначе почему он ругается на отсутствие вполне стандартного члена библиотеки.
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
17.04.2014, 22:49 12
Цитата Сообщение от AceOfSpades Посмотреть сообщение
По поводу этих ошибок сказать трудно, что компилятору не нравится, может нет нужных зависимостей, иначе почему он ругается на отсутствие вполне стандартного члена библиотеки.
Этот метод появился только в С++11. Возможно в VS2010 уже были реализованы некоторые фичи заранее.
Автор, ИМХО, собирает проект в каком-то GCC.
Ключевое слово typename не обязательно в той ситуации в VS2010 (как и в любой другой студии) исходя из отсутствия реализации в компиляторе two-phase name lookup. Некоторые считают, что это хорошо, однако подобный код все-таки остается нестандартным. И GCC вполне обоснованно его не собирает.
0
54 / 53 / 5
Регистрация: 14.08.2012
Сообщений: 252
17.04.2014, 23:21 13
Цитата Сообщение от DrOffset Посмотреть сообщение
однако подобный код все-таки остается нестандартным. И GCC вполне обоснованно его не собирает.
Возможно. В таком случае нужно сделать код более "стандартным".
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
17.04.2014, 23:36 14
AceOfSpades, выше я уже показывал как
1
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 86
18.04.2014, 10:05  [ТС] 15
События сделал. ВОт например
C++
1
2
3
4
5
6
EventHandler<EventArgs> OnStop;
 
    void StopEvent(){
        if (OnStop != 0)
            OnStop(this, new EventArgs());
    }
В классе NMclient
в main
C++
1
2
3
4
5
6
7
void MyMeth1(void* obj, ClientEventArgs* args){
    
}
int main(){
    NMClient* client = new NMClient("127.0.0.1", 9000);
    client->OnStop += MyMeth1;
}
Выдает

main.cpp:5:25: error: ‘ClientEventArgs’ has not been declared
In file included from main.cpp:1:0:
NMClient.cpp: In function ‘int main()’:
NMClient.cpp:67:26: error: ‘EventHandler<EventArgs> NMClient::OnStop’ is private
main.cpp:10:10: error: within this context
main.cpp:10:20: error: invalid conversion from ‘void (*)(void*, int*)’ to ‘EventHandler<EventArgs>::CallBackFunction {aka void (*)(void*, EventArgs*)}’ [-fpermissive]
In file included from NMClient.cpp:14:0,
from main.cpp:1:
EventHandler.h:18:30: error: initializing argument 1 of ‘EventHandler<EventArgs>& EventHandler<EventArgs>::operator+=(EventHandler<EventArgs>::CallBackFunction) [with EventArgs = EventArgs; EventHandler<EventArgs> = EventHandler<EventArgs>; EventHandler<EventArgs>::CallBackFunction = void (*)(void*, EventArgs*)]’ [-fpermissive]
0
54 / 53 / 5
Регистрация: 14.08.2012
Сообщений: 252
18.04.2014, 10:22 16
Типы параметров не совпадают. В вашем методе тип ClientEventArgs, а в классе определен хэндлер с типом EventArgs. Либо приводите тип, либо хэндлер объявите тоже с типом ClientEventArgs.
И ошибки:
ClientEventArgs - не объявлен (может инклуд забыли?)
OnStop - объявите публичным, иначе он не виден снаружи класса

Добавлено через 11 минут
Правила создания событий лучше делать такие:
Имя события - что-то случилось, в вашем случае Stopped.
Метод, вызывающий событие - защищенный виртуальный с приставкой On, в вашем случае
protected: virtual void OnStopped();
И всё-таки не с нулем лучше сравнивать, а с NULL (null), если он у вас не определен, то добавьте перед описанием класса #define null 0
Это общепринятый стиль в C#, раз уж вы его в С++ решили перетащить.
1
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
18.04.2014, 15:05 17
Цитата Сообщение от AceOfSpades Посмотреть сообщение
И всё-таки не с нулем лучше сравнивать, а с NULL (null), если он у вас не определен, то добавьте перед описанием класса #define null 0
Все-таки лучше так не делать. NULL определен, но он используется для указателей, а в современном языке его лучше вообще не использовать, вместо него уже есть стандартный nullptr. Если очень хочется именно null, то лучше константу объявить.
C++
1
static const int null = 0;
0
54 / 53 / 5
Регистрация: 14.08.2012
Сообщений: 252
18.04.2014, 16:19 18
Цитата Сообщение от DrOffset Посмотреть сообщение
NULL определен, но он используется для указателей
Речь же шла о подобии в C#, а там все ссылочные типы (классы и указатели) могут быть null.
static const int null = 0; - если больше нигде не нужно использовать null в других файлах, то можно.

Чем #define хуже? Мы же определяем новую семантику для типа, а не переменную.
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
18.04.2014, 16:50 19
Цитата Сообщение от AceOfSpades Посмотреть сообщение
Речь же шла о подобии в C#
Речь шла о портировании на С++, а это разные вещи. В каждом языке есть свои нюансы, и их надо учитывать. Вслепую копировать подходы из одного языка в другой - неправильно.
Цитата Сообщение от AceOfSpades Посмотреть сообщение
а там все ссылочные типы (классы и указатели) могут быть null.
Вот в этом коде нет ссылочных типов. И здесь мы сравниваем значение а с NULL, а не ссылку на а с NULL. Поэтому, если не имелось в виду сравнение с нулем, то в С++ этот код бессмысленный.
C++
1
inline bool operator==(int a) { return (a == NULL) && (callBackList.size() == 0); }
Цитата Сообщение от AceOfSpades Посмотреть сообщение
Чем #define хуже?
Тем, что это макроподстановка. Отдельный язык по сути, с С++ он никак не связан и система типов С++ не сможет проконтролировать операции с ним. Это просто замена в тексте.
Цитата Сообщение от AceOfSpades Посмотреть сообщение
Мы же определяем новую семантику для типа, а не переменную.
Препроцессор ничего не знает про типы. Это такая автоматизированная автозамена.
0
54 / 53 / 5
Регистрация: 14.08.2012
Сообщений: 252
18.04.2014, 17:34 20
Цитата Сообщение от DrOffset Посмотреть сообщение
Препроцессор ничего не знает про типы. Это такая автоматизированная автозамена.
При чём тут препроцессор? Это его проблемы, что он не знает про типы, но человек же знает. Поэтому макроподстановки и полезны, делают язык более гибким.
Выражение OnStop != 0 для меня, например означает, что OnStop имеет семантику значения (хотя в данном случае это не так), что вызывает дискомфорт или даже путаницу (почему бы тогда не сравнивать с 1, 2 ...).
Выражение OnStop != null (уже ясно дает понять, что речь идет прежде всего о типе (неважно, указатель это или что-то другое). Хотя формальной разницы тут нет. Объявление null как константы опять же вносит семантику значения...
В общем не буду больше с вами спорить.
0
18.04.2014, 17:34
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.04.2014, 17:34
Помогаю со студенческими работами здесь

Функция обратного вызова
Приветствую всех. Создаю свой класс и при определенном событии в экземпляре этого класса должна...

Процедура обратного вызова
Немного запутался в процедурах обратного вызова, в процедурных типах. Есть DLL и описание к ней....

Функция обратного вызова
Функция обратного вызова это та, которая передаётся в качестве аргумента другой функции и внутри...

Функция обратного вызова
Доброго времени суток уважаемые гуру программирования! Нужна помощь! В описании к DLL есть функция:...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru