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

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

Восстановить пароль Регистрация
 
 
diplomat1129
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 83
14.04.2014, 14:48     Заменить делегаты функциями обратного вызова #1
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));
        }
Мне надо сделать аналог на с++. с делегатами разобрался - их надо заменить функциями обратного вызова..
а вот как быть с событиями. есть ли аналог?или как то же обходятся люди ?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.04.2014, 14:48     Заменить делегаты функциями обратного вызова
Посмотрите здесь:

Метод обратного пузырька(камешка) C++
C++ Функция обратного вызова
оформить решение в виде функции следующими способами: 1. функция расположена после ее вызова; 2. функция расположена после до ее вызова; 3. функ C++
C++ нужно чтобы функция располагалась до ее вызова, после ее вызова и в другом файле. Как это сделать?
C++ Делегаты и события
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
AceOfSpades
41 / 40 / 3
Регистрация: 14.08.2012
Сообщений: 231
14.04.2014, 20:13     Заменить делегаты функциями обратного вызова #2
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Делается довольно несложно. Проект прилагаю.
Класс EventHandler реализует работу по подписке/отписке и вызову обработчиков события. Весь остальной код, предполагается, что пишет пользователь, и использует "библиотечный" EventHandler для определения своих событий.
Единственное ограничение: обработчики событий должны быть определены вне класса (а если им требуется доступ к внутренностям класса, то просто объявить их друзьями). Хотя, ничего плохого в этом не вижу, наоборот, код структурируется.
Вложения
Тип файла: 7z Test.7z (2.1 Кб, 11 просмотров)
diplomat1129
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 83
17.04.2014, 19:22  [ТС]     Заменить делегаты функциями обратного вызова #3
Ошибка почему-то.когда использую ваш заголовочный файл
AceOfSpades
41 / 40 / 3
Регистрация: 14.08.2012
Сообщений: 231
17.04.2014, 19:25     Заменить делегаты функциями обратного вызова #4
Какая?
diplomat1129
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 83
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); }
DrOffset
6459 / 3833 / 885
Регистрация: 30.01.2014
Сообщений: 6,629
17.04.2014, 19:42     Заменить делегаты функциями обратного вызова #6
Сообщение было отмечено автором темы, экспертом или модератором как ответ
diplomat1129,
Там ошибка. Связанная с тем, что VC++ не требует наличия ключевого слова typename в этой ситуации (это объясняется отсутствием в VC++ two-phase name lookup, но это тянет на отдельную тему), хотя по стандарту оно должно быть.
В общем, надо так:
C++
1
for (typename list<CallBackFunction>::const_iterator it = callBackList.cbegin(); it != callBackList.cend(); it++)
diplomat1129
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 83
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); }
DrOffset
6459 / 3833 / 885
Регистрация: 30.01.2014
Сообщений: 6,629
17.04.2014, 19:48     Заменить делегаты функциями обратного вызова #8
diplomat1129, Насчет этого наверное лучше у автора спросить. Но мне кажется, что можно просто заменить на ноль.
diplomat1129
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 83
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++)

если не использовать в другом классе, а просто компилить, то компилиться без ошибок
DrOffset
6459 / 3833 / 885
Регистрация: 30.01.2014
Сообщений: 6,629
17.04.2014, 20:18     Заменить делегаты функциями обратного вызова #10
diplomat1129, C++11 нужно, чтобы это работало. -std=c++11
AceOfSpades
41 / 40 / 3
Регистрация: 14.08.2012
Сообщений: 231
17.04.2014, 22:41     Заменить делегаты функциями обратного вызова #11
Всё это возможно из-за того, что я не учитывал особенности VC++ и C++11, т.к. первый категорически не перевариваю (из-за личных взглядов), а для второго у меня нет поддержки компилятора.
Изначально я создавал проект для этого файла как обычный Win32 без всяких там .net и clr. Среда разработки VS2010.
По поводу этих ошибок сказать трудно, что компилятору не нравится, может нет нужных зависимостей, иначе почему он ругается на отсутствие вполне стандартного члена библиотеки.
DrOffset
6459 / 3833 / 885
Регистрация: 30.01.2014
Сообщений: 6,629
17.04.2014, 22:49     Заменить делегаты функциями обратного вызова #12
Цитата Сообщение от AceOfSpades Посмотреть сообщение
По поводу этих ошибок сказать трудно, что компилятору не нравится, может нет нужных зависимостей, иначе почему он ругается на отсутствие вполне стандартного члена библиотеки.
Этот метод появился только в С++11. Возможно в VS2010 уже были реализованы некоторые фичи заранее.
Автор, ИМХО, собирает проект в каком-то GCC.
Ключевое слово typename не обязательно в той ситуации в VS2010 (как и в любой другой студии) исходя из отсутствия реализации в компиляторе two-phase name lookup. Некоторые считают, что это хорошо, однако подобный код все-таки остается нестандартным. И GCC вполне обоснованно его не собирает.
AceOfSpades
41 / 40 / 3
Регистрация: 14.08.2012
Сообщений: 231
17.04.2014, 23:21     Заменить делегаты функциями обратного вызова #13
Цитата Сообщение от DrOffset Посмотреть сообщение
однако подобный код все-таки остается нестандартным. И GCC вполне обоснованно его не собирает.
Возможно. В таком случае нужно сделать код более "стандартным".
DrOffset
6459 / 3833 / 885
Регистрация: 30.01.2014
Сообщений: 6,629
17.04.2014, 23:36     Заменить делегаты функциями обратного вызова #14
AceOfSpades, выше я уже показывал как
diplomat1129
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 83
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]
AceOfSpades
41 / 40 / 3
Регистрация: 14.08.2012
Сообщений: 231
18.04.2014, 10:22     Заменить делегаты функциями обратного вызова #16
Типы параметров не совпадают. В вашем методе тип ClientEventArgs, а в классе определен хэндлер с типом EventArgs. Либо приводите тип, либо хэндлер объявите тоже с типом ClientEventArgs.
И ошибки:
ClientEventArgs - не объявлен (может инклуд забыли?)
OnStop - объявите публичным, иначе он не виден снаружи класса

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

Чем #define хуже? Мы же определяем новую семантику для типа, а не переменную.
DrOffset
6459 / 3833 / 885
Регистрация: 30.01.2014
Сообщений: 6,629
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 Посмотреть сообщение
Мы же определяем новую семантику для типа, а не переменную.
Препроцессор ничего не знает про типы. Это такая автоматизированная автозамена.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.04.2014, 17:34     Заменить делегаты функциями обратного вызова
Еще ссылки по теме:

C++ Нейронные сети обратного распространения
C++ Метод обратного распространения ошибки
Метод обратного распространения ошибки C++

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

Или воспользуйтесь поиском по форуму:
AceOfSpades
41 / 40 / 3
Регистрация: 14.08.2012
Сообщений: 231
18.04.2014, 17:34     Заменить делегаты функциями обратного вызова #20
Цитата Сообщение от DrOffset Посмотреть сообщение
Препроцессор ничего не знает про типы. Это такая автоматизированная автозамена.
При чём тут препроцессор? Это его проблемы, что он не знает про типы, но человек же знает. Поэтому макроподстановки и полезны, делают язык более гибким.
Выражение OnStop != 0 для меня, например означает, что OnStop имеет семантику значения (хотя в данном случае это не так), что вызывает дискомфорт или даже путаницу (почему бы тогда не сравнивать с 1, 2 ...).
Выражение OnStop != null (уже ясно дает понять, что речь идет прежде всего о типе (неважно, указатель это или что-то другое). Хотя формальной разницы тут нет. Объявление null как константы опять же вносит семантику значения...
В общем не буду больше с вами спорить.
Yandex
Объявления
18.04.2014, 17:34     Заменить делегаты функциями обратного вызова
Ответ Создать тему
Опции темы

Текущее время: 23:01. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru