Как стать автором
Поиск
Написать публикацию
Обновить

Делегат на C++

Всем привет!

Всем известно, что в С++ нет делегатов. А зачем? Есть указатели на функции, коими, по сути, и являются делегаты. Но есть одно но: если нужно сделать указатель на метод класса, возникают проблемы.
Я решил написать шаблонный класс, который и будет выполнять данный функционал.
Тут нужны знания С++ и ООП (полиморфизма).

#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. Чаще всего такой делегат можно использовать при создании своего таймера или потока. Но он подходит и для реализации какой-либо событийной модели.

На этом все. Всем спасибо за внимание!
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.