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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
diplomat1129
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 83
#1

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

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

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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.04.2014, 14:48
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Заменить делегаты функциями обратного вызова (C++):

Функция обратного вызова - C++
#undef UNICODE #include &lt;windows.h&gt; #include &quot;resource.h&quot; #include &lt;iostream&gt; #include &lt;fstream&gt; using namespace std; HWND...

Стрелка в описании функции обратного вызова - C++
#include &lt;iostream&gt; #include &lt;algorithm&gt; std::string s = &quot;hello&quot;; auto end = std::unique(s.begin(), s.end(), (char a, char b) -&gt; bool...

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

нужно чтобы функция располагалась до ее вызова, после ее вызова и в другом файле. Как это сделать? - C++
#include &lt;iostream&gt; #include &lt;conio.h&gt; using namespace std; int n, *c; void fun(int a, int b) { for (int i = 0; i &lt;...

оформить решение в виде функции следующими способами: 1. функция расположена после ее вызова; 2. функция расположена после до ее вызова; 3. функ - C++
оформить решение в виде функции следующими способами: 1. функция расположена после ее вызова; 2. функция расположена после до ее...

Делегаты и события - C++
Всем доброго времени суток. Понадобилось код из C# переделать на C++. Кода в принципе не много и он не сложен в понимании. Но сам Я на C#...

26
AceOfSpades
44 / 43 / 3
Регистрация: 14.08.2012
Сообщений: 246
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
DrOffset
7351 / 4451 / 1009
Регистрация: 30.01.2014
Сообщений: 7,292
18.04.2014, 15:05 #17
Цитата Сообщение от AceOfSpades Посмотреть сообщение
И всё-таки не с нулем лучше сравнивать, а с NULL (null), если он у вас не определен, то добавьте перед описанием класса #define null 0
Все-таки лучше так не делать. NULL определен, но он используется для указателей, а в современном языке его лучше вообще не использовать, вместо него уже есть стандартный nullptr. Если очень хочется именно null, то лучше константу объявить.
C++
1
static const int null = 0;
0
AceOfSpades
44 / 43 / 3
Регистрация: 14.08.2012
Сообщений: 246
18.04.2014, 16:19 #18
Цитата Сообщение от DrOffset Посмотреть сообщение
NULL определен, но он используется для указателей
Речь же шла о подобии в C#, а там все ссылочные типы (классы и указатели) могут быть null.
static const int null = 0; - если больше нигде не нужно использовать null в других файлах, то можно.

Чем #define хуже? Мы же определяем новую семантику для типа, а не переменную.
0
DrOffset
7351 / 4451 / 1009
Регистрация: 30.01.2014
Сообщений: 7,292
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
AceOfSpades
44 / 43 / 3
Регистрация: 14.08.2012
Сообщений: 246
18.04.2014, 17:34 #20
Цитата Сообщение от DrOffset Посмотреть сообщение
Препроцессор ничего не знает про типы. Это такая автоматизированная автозамена.
При чём тут препроцессор? Это его проблемы, что он не знает про типы, но человек же знает. Поэтому макроподстановки и полезны, делают язык более гибким.
Выражение OnStop != 0 для меня, например означает, что OnStop имеет семантику значения (хотя в данном случае это не так), что вызывает дискомфорт или даже путаницу (почему бы тогда не сравнивать с 1, 2 ...).
Выражение OnStop != null (уже ясно дает понять, что речь идет прежде всего о типе (неважно, указатель это или что-то другое). Хотя формальной разницы тут нет. Объявление null как константы опять же вносит семантику значения...
В общем не буду больше с вами спорить.
0
DrOffset
7351 / 4451 / 1009
Регистрация: 30.01.2014
Сообщений: 7,292
18.04.2014, 18:30 #21
Цитата Сообщение от AceOfSpades Посмотреть сообщение
При чём тут препроцессор?
В С++ не принято использовать препроцессор для таких вещей.

Цитата Сообщение от AceOfSpades Посмотреть сообщение
Объявление null как константы опять же вносит семантику значения...
Чтобы мы тут не написали (хоть define, хоть что), семантика значения всегда будет. Потому что переменная `а` в примере выше - это значение, а не ссылка.

Цитата Сообщение от AceOfSpades Посмотреть сообщение
В общем не буду больше с вами спорить.
Смысл спорить? Я говорю о том, что нельзя просто брать и перекладывать правила написания кода с С# на С++, потому что многие вещи в С++ отличаются.

AceOfSpades, в общем тут понятно, что у вас есть определенные знания С# и С++, но очевидно, что знание С# выше. Поэтому я хочу пояснить насчет значений и ссылок, и проверок на NULL в С++.
Вот для примера такой код на С++. В комментариях объясню чем отличаются эти методы.
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
class A
{
public:
    // Здесь а имеет семантику значения, `а` располагается на стеке и `а` копируется при вызове operator==.
    // Поэтому, в данной ситуации, проверку на NULL делать не 
    // нужно (мы не сможем, даже если захотим, записать ее так, 
    // чтобы сохранить требуемую семантику).`а` - это значение.
    bool operator==(A a) const
    {
        return a.value == value;
    }
    // Здесь `а`, как ни странно, тоже имеет семантику значения, И проверку на NULL делать тоже не нужно. 
    // Ссылка в С++ имеет семантику значения (не может быть NULL -
    // это гарантируется языком).
    // Все операции, производимые над ссылкой, на самом деле будут произведены над объектом, 
    // на который она ссылается. В то же время копирования аргумента не произойдет, 
    // как в первом случае, потому что ссылка также имеет и свойства указателя.
    bool operator==(A const & a) const
    {
        return a.value == value;
    }
    // В этой ситуации мы делаем проверку на NULL, потому что `a` - это указатель. Он может содержать NULL, 
    // но может содержать и адрес реального объекта
    bool operator==(A const * a) const
    {
        return a != NULL && a->value == value;
    }
 
private:
    int value;
};
Как видно, это все несколько отличается от того, что предлагает С#, поэтому не учитывать эти особенности при переносе нельзя.
0
AceOfSpades
44 / 43 / 3
Регистрация: 14.08.2012
Сообщений: 246
18.04.2014, 19:54 #22
Просто мы друг друга не понимаем)) я об одном, вы о другом.
0
DrOffset
7351 / 4451 / 1009
Регистрация: 30.01.2014
Сообщений: 7,292
18.04.2014, 20:31 #23
Цитата Сообщение от AceOfSpades Посмотреть сообщение
Просто мы друг друга не понимаем)) я об одном, вы о другом.
Возможно.
Я сейчас просмотрел еще раз ваш код и вопросы автора. Если я правильно понял, то данные операторы
C++
1
2
inline bool operator==(int a) { return (a == NULL) && (callBackList.size() == 0); }
inline bool operator!=(int a) { return (a == NULL) && (callBackList.size() != 0); }
Нужны для того, что бы работала данная проверка?
C++
1
2
3
4
void StopEvent(){
    if (OnStop != NULL)
        OnStop(this, new EventArgs());
}
Все что, что я говорил выше верно для этого случая. В С++ не принято так делать, этот код запутает плюсовика, как запутал сейчас меня. NULL, как я объяснял выше, применяется для указателей. Очевидно, что, здесь никаких указателей нет. Поэтому, нужно либо изменить операторы следующим образом (кстати, нет ли тут ошибки, в обоих операторах сравнение с NULL и &&, но этого вопроса я сейчас не касаюсь):
C++
1
2
inline bool operator==(void * a) { return (a == NULL) && (callBackList.size() == 0); }
inline bool operator!=(void * a) { return (a == NULL) && (callBackList.size() != 0); }
Однако это тоже не будет иметь нужного эффекта. Т.к. может спровоцировать на сравнение с другими указателями, отличными от NULL, хотя этого здесь не требуется.
Поэтому очевидным и правильным с т.з. программирования на С++, но в то же время идеологически будет соответствовать смыслу, который он несет в С#, будет такой оператор вместо двух вышеприведенных:
C++
1
inline operator bool() const { return callBackList.size() != 0; }
Соответственно проверка будет выглядеть так:
C++
1
2
3
4
void StopEvent() {
     if(OnStop)
         OnStop(this, new EventArgs());
}
Добавлено через 7 минут
addition:
Я в первую очередь пишу это здесь не для того, что бы кого-то принизить или уличить в ошибке, а только лишь из соображений корректности ответа. Слишком уж велик шанс неправильно научить человека.
0
AceOfSpades
44 / 43 / 3
Регистрация: 14.08.2012
Сообщений: 246
18.04.2014, 20:34 #24
Да, вы всё правильно говорите, но автор же хотел синтаксис как в шарпе, поэтому так. На плюсах я бы вообще так не делал, есть другие способы и библиотеки для работы с событиями.

Цитата Сообщение от DrOffset Посмотреть сообщение
кстати, нет ли тут ошибки, в обоих операторах сравнение с NULL и &&, но этого вопроса я сейчас не касаюсь
Ошибки нет.

Цитата Сообщение от DrOffset Посмотреть сообщение
Однако это тоже не будет иметь нужного эффекта. Т.к. может спровоцировать на сравнение с другими указателями, отличными от NULL, хотя этого здесь не требуется.
перегрузка определена только для типов int, поэтому сравнение с указателями вызовет ошибку компиляции.
0
DrOffset
7351 / 4451 / 1009
Регистрация: 30.01.2014
Сообщений: 7,292
18.04.2014, 20:47 #25
Цитата Сообщение от AceOfSpades Посмотреть сообщение
перегрузка определена только для типов int, поэтому сравнение с указателями вызовет ошибку компиляции.
Именно это меня и смутило. Я привел две перегрузки с void*, поэтому завел речь про указатели. Это было предложено как пример некорректного выхода из ситуации (с учетом пояснения, что NULL применяется для указателей) - в общем, видимо это не было замечено при чтении моего поста .
Цитата Сообщение от AceOfSpades Посмотреть сообщение
Ошибки нет
Да, согласен, нет.
Цитата Сообщение от AceOfSpades Посмотреть сообщение
но автор же хотел синтаксис как в шарпе
Пусть автор меня поправит, но мне показалось, что он хотел поведение как в C#, а не синтаксис...
0
AceOfSpades
44 / 43 / 3
Регистрация: 14.08.2012
Сообщений: 246
18.04.2014, 20:56 #26
Цитата Сообщение от DrOffset Посмотреть сообщение
Я привел две перегрузки с void*, поэтому завел речь про указатели
Да, не доглядел, сорри
0
diplomat1129
0 / 0 / 0
Регистрация: 11.02.2013
Сообщений: 83
18.04.2014, 23:38  [ТС] #27
Да, хотел события как в С#, а не синтаксис. Спасибо вам всем )
0
18.04.2014, 23:38
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.04.2014, 23:38
Привет! Вот еще темы с ответами:

Собираются ли вводить делегаты? - C++
или так и собираются строго придерживаться тому, что есть - писать уже с имеющегося кучу кода вместо того, чтобы сделать это встроенным?

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

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

Интерфейсы обратного вызова - C#
Как часто ли Вы используете интерфейсы обратного вызова? Если да, то для чего обычно? :)


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

Или воспользуйтесь поиском по форуму:
27
Ответ Создать тему
Опции темы

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