Pull to refresh

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

На этом все. Всем спасибо за внимание!
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.