{{notification.text}}

MirGames

Прохожий
08.08.16 17:21
0

Делаю простейшее окно на WinApi, только на сей раз пишу на С++. Создание и работу окна оформила в виде класса и все нормально работает. Но вот чего хочется:
когда я писала аналогичную вещь на Дельфи, я использовала такую чудесную вещь, кажется называется Method Pointer, впрочем, я не уверена.
Это когда есть поле/свойство класса, например. OnRender: procedure, которому можно назначить любую процедуру: Wnd.onRender:=MyProc, а в основном оконном цикле написать: if Assigned(OnRender) then OnRender.

Или когда делаешь поле класса procedure RenderEvent(Sender:TObject); virtual; и объявляешь тип TRenderEvent=procedure(Sender: TObject) of object;

Хорошо это или плохо - не знаю, но мне очень нравилось, было удобно. А вот как такое написать на С++? Что-то я перерыла инет и не вижу, наверное очень сильно туплю.

#1
Dan
The One
09.08.16 12:33
0

в самом языке с++ таких удобных конструкций нет и нужно их либо писать самому, либо использовать std. второй вариант намного проще, но не очень кросплатформенный т.к. требует поддержку с++11 стандарта.
std вариант:

#include <functional>

//объявление функции (TRenderEvent=procedure(Sender: TObject) of object;):
typedef std::function<void(void* Sender)> TRenderEvent;
...
//класс в котором эта функция будет вызываться:
class TMyClass {
public:
  TMyClass();
  //RenderEvent(Sender:TObject); virtual;
  virtual void RenderEvent(void* Sender);
};
...
//переменная котораю будет держать указатель на функцию (Wnd.onRender):
TRenderEvent WndOnRender;
...
//конструктор класса:
TMyClass::TMyClass() {
  //привязываем функцию к переменной:
  //Wnd.onRender := MyProc
  WndOnRender = std::bind(&TMyClass::RenderEvent, this, std::placeholders::_1);
}
...
//вызов функции через переменную (в данном случае Sender = NULL):
//if Assigned(OnRender) then OnRender.
if (WndOnRender != NULL) WndOnRender(NULL);

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

Отредактировано: 09.08.16 12:33
#2
09.08.16 13:59
0

Эта штука называется "делегаты". По запросу "делегаты C++" гугл выдаст немало результатов разной степени навороченности. Вот, например. Еще на RSDN видел статью по делегатам, которой вдохновлялся, когда делал свои multicast делегаты для Delphi, но с полпинка не нашел.

#3
Прохожий
09.08.16 13:59
0

Очень интересно, спасибо. Мне кроссплатформенность не нужна, так что подойдет.

Один очень безграмотный вопрос: я в сети наткнулась на сущность под названием Delegate. Из того, что я смогла понять, мне показалось, что это может помочь реализовать подобный механизм. Показалось?

#4
Прохожий
09.08.16 14:03
0

Vga
Так это и есть делегаты??? Это ты на мой пост ответил или на пост Dan?

#5
Dan
The One
09.08.16 14:05
0

Delegate это и есть то что тебе нужно. понятие делегатов в себя так же включает и группы указателей на функции (multicast delegate), это когда один делегат может разом вызвать сразу несколько функций у него зарегистрированых.

#6
09.08.16 14:06
0

Я ответил на начальный пост) Да, это и есть делегаты. Приблизительно их можно назвать ссылками на метод конкретного объекта. В отличие от дельфи, в С++ указатель на метод (называемый там функция-член класса) довольно сложная штука и к тому же несовместимая между разными типами ФЧК (статические, виртуальные, etc), из-за этого и приходится городить шаблонную магию.

#7
Прохожий
09.08.16 14:20
0

Dan
Я честно скопипастила ваш пост, но компилятор не одобрил, особенно строку с объявлением TRenderEvent.
Что-то я не дописала?

Осваиваю С++, используя MS Visual Studio 2008

У меня что, слишком старый MSVS ?

Отредактировано: 09.08.16 14:24
#8
09.08.16 14:24
0

Рискну предположить, что компилятор 2008 года не поддерживает С++ стандарта 2011 года.

#9
Dan
The One
09.08.16 14:31
0

Рискну предположить, что компилятор 2008 года не поддерживает С++ стандарта 2011 года

именно так. а без std::function нужно всё делать в ручную и при том без vararg шаблонов. поэтому лучший вариант, я думаю, будет через дефайны объявлять функции с разным числом параметров.

#10
09.08.16 14:33
0

Упомянутые мной делегаты с RSDN решали вопрос vararg'а через макросы. В целом, по внешнему интерфейсу библиотечка у них получилась вполне симпатичная.

#11
Dan
The One
09.08.16 14:33
0

а ещё лучше поставить vs2010, на сколько я знаю в нём есть огранченный функционал с++11 стандарта включая std::function

#12
Прохожий
09.08.16 14:36
0

Да мне не сложно и выше версию поставить, знать бы только, какая из них менее глюкавая. Я все-таки языка-то не знаю, хочется пока что попроще. 2008 у меня осталась со времен компиляции Star Control`а.

#15
Прохожий
15.08.16 15:33
0

Все, сдаюсь - как расшифровывается эта строчка?

typedef std::function<void(void* Sender)> TRenderEvent;

#16
Dan
The One
16.08.16 06:06
0

это объявление типа функции type TRenderEvent = procedure(Sender: TObject) of object;
вместо TObject я поставил просто указатель ( void* )
std::function это шаблон для объявления функции, в него передаётся описание этой функции: void(void* Sender)
это значит что она описывает любые функции вида void MyFunc(void* MyParam);

Отредактировано: 16.08.16 06:06
#{{post.Index}}
{{post.Author.Login}}
{{post.CreatedDate | date:'dd.MM.yy HH:mm'}}
{{post.VotesRating}}
Отредактировано: {{post.UpdatedDate | date:'dd.MM.yy HH:mm'}}