Всем привет!
Всем известно, что в С++ нет делегатов. А зачем? Есть указатели на функции, коими, по сути, и являются делегаты. Но есть одно но: если нужно сделать указатель на метод класса, возникают проблемы.
Я решил написать шаблонный класс, который и будет выполнять данный функционал.
Тут нужны знания С++ и ООП (полиморфизма).
Обратите внимание, что, хоть переменная _delegate и является указателем на DelegateCallbackBase, в функции Connect мы все же создаем объект класса DelegateCallback. Это сделано, т.к. Listener изначально неизвестен, поэтому пришлось ввести базовый класс DelegateCallbackBase.
Самое время протестировать делегат:
Теперь каждый раз, когда будет будет вызываться метод SomeMethod класса Sender, будет вызываться и метод MyDelegateCallback класса Receiver. Чаще всего такой делегат можно использовать при создании своего таймера или потока. Но он подходит и для реализации какой-либо событийной модели.
На этом все. Всем спасибо за внимание!
Всем известно, что в С++ нет делегатов. А зачем? Есть указатели на функции, коими, по сути, и являются делегаты. Но есть одно но: если нужно сделать указатель на метод класса, возникают проблемы.
Я решил написать шаблонный класс, который и будет выполнять данный функционал.
Тут нужны знания С++ и ООП (полиморфизма).
#include <iostream>
class DelegateCallbackBase
{
public:
virtual void notify() = 0;
};
template<typename Listener> class DelegateCallback : public DelegateCallbackBase
{
private:
Listener *_object;
void (Listener::*_member)();
public:
DelegateCallback(Listener *object, void (Listener::*member)())
{
this->_object = object;
this->_member = member;
}
virtual void notify()
{
(this->_object->*this->_member)();
}
};
class Delegate
{
private:
DelegateCallbackBase *_delegate;
public:
Delegate()
{
}
~Delegate()
{
}
template<typename Listener> void Connect(Listener *object, void (Listener::*member)())
{
this->_delegate = new DelegateCallback<Listener>(object, member);
}
void operator()()
{
this->_delegate->notify();
}
};
Обратите внимание, что, хоть переменная _delegate и является указателем на DelegateCallbackBase, в функции Connect мы все же создаем объект класса DelegateCallback. Это сделано, т.к. Listener изначально неизвестен, поэтому пришлось ввести базовый класс DelegateCallbackBase.
Самое время протестировать делегат:
class Sender
{
public:
Delegate MyDelegate;
void SomeMethod()
{
MyDelegate();
}
};
class Receiver
{
public:
Receiver(Sender *sender)
{
sender->MyDelegate.Connect<Receiver>(this, &Receiver::MyDelegateCallback);
}
void MyDelegateCallback()
{
std::cout << "Hello from delegate!" << std::endl;
}
};
int main(int argc, char **argv)
{
Sender sender;
Receiver receiver(&sender);
sender.SomeMethod();
return 0;
}
Теперь каждый раз, когда будет будет вызываться метод SomeMethod класса Sender, будет вызываться и метод MyDelegateCallback класса Receiver. Чаще всего такой делегат можно использовать при создании своего таймера или потока. Но он подходит и для реализации какой-либо событийной модели.
На этом все. Всем спасибо за внимание!