C++ 封装代理,单播以及多播

C++ 封装代理,单播以及多播


前言

之前我们有写过以及封装过代理,但是不够完善,我们要在此基础上进行完善
这个是以前我们封装的代理点击跳转

基础封装

FDelegateBase :是所以代理的基类,只有一个Execute 执行方法

template<typename TReturn, typename ...InParams>
class FDelegateBase
{
public:
	virtual TReturn Execute(InParams &&...Params)
	{
		return TReturn();
	}
};

FObjectDelegate :用于成员函数代理

template<typename TObjectInstance, typename TReturn, typename ...InParams>
class FObjectDelegate : public FDelegateBase<TReturn, InParams...>
{
public:
	FObjectDelegate(TObjectInstance* InInstance, TReturn(TObjectInstance::* InFunction)(InParams...))
		:ObjectInstance(InInstance), InstanceFunction(InFunction)
	{

	}

	virtual TReturn Execute(InParams &&...Params) override
	{
		return (ObjectInstance->*InstanceFunction)(forward<InParams>(Params)...);
	}

	TObjectInstance* ObjectInstance;
	TReturn(TObjectInstance::* InstanceFunction)(InParams...);
};

FFunctionDelegate :用于非成员函数代理

template<typename TReturn, typename ...InParams>
class FFunctionDelegate : public FDelegateBase<TReturn, InParams...>
{
public:
	FFunctionDelegate(TReturn(*InFunction)(InParams...))
		:Function(InFunction)
	{

	}

	virtual TReturn Execute(InParams &&...Params) override
	{
		return (*Function)(forward<InParams>(Params)...);
	}

	TReturn(*Function)(InParams...);
};

FDelegate 是真实要创建代理的类,其中提供了绑定、解绑、创建代理的方法
之后我们的单播和多播只需要继承此类即可

template<typename TReturn, typename ...InParams>
class FDelegate
{
public:
	FDelegate()
		: Ptr(nullptr)
	{

	}

	template<typename TObjectInstance>
	void Bind(TObjectInstance* InObjectInstance, TReturn(TObjectInstance::* InObjectFunction)(InParams...))
	{
		ResetPtr();
		Ptr = new FObjectDelegate<TObjectInstance, TReturn, InParams...>(InObjectInstance, InObjectFunction);
	}

	void Bind(TReturn(*InObjectFunction)(InParams...))
	{
		ResetPtr();
		Ptr = new FFunctionDelegate<TReturn, InParams...>(InObjectFunction);
	}

	void UnBind()
	{
		ResetPtr();
	}

	TReturn Execute(InParams &&...Params)
	{
		if (Ptr)
		{
			return Ptr->Execute(forward<InParams>(Params)...);
		}

		return TReturn();
	}

	template<typename TObjectInstance>
	static FDelegate<TReturn, InParams...> Create(TObjectInstance* InObjectInstance, TReturn(TObjectInstance::* InObjectFunction)(InParams...))
	{
		FDelegate<TReturn, InParams...> del;
		del.Bind(InObjectInstance, InObjectFunction);
		return del;
	}

	static FDelegate<TReturn, InParams...> Create(TReturn(*InObjectFunction)(InParams...))
	{
		FDelegate<TReturn, InParams...> del;
		del.Bind(InObjectFunction);
		return del;
	}

private:
	void ResetPtr()
	{
		if (Ptr)
		{
			delete Ptr;
			Ptr = nullptr;
		}
	}

private:
	FDelegateBase<TReturn, InParams...>* Ptr;
};

完善单播

我们继承之前的基类

template<typename TReturn,typename ...InParams>
class FSingleDelegate : public FDelegate<TReturn, InParams...>
{
public:
	FSingleDelegate():FDelegate<TReturn, InParams...>()
	{

	}
};

可以如下使用

	auto Del = FDelegate<int, int, int>::Create([](int a, int b)->int 
		{
			return a + b;
		});
	int ret = Del.Execute(1, 2);
	cout << ret << endl;

	Del.UnBind();

为了我们更方便的使用我们可以包裹成为宏

#define SIMPLE_SINGLE_DELEGATE(Name,Return,...) FSingleDelegate<Return,__VA_ARGS__> Name
	SIMPLE_SINGLE_DELEGATE(TestDelegate, int, int, int);
	TestDelegate.Bind([](int a, int b)->int
		{
			return a + b;
		});
	int Ret1 = TestDelegate.Execute(2, 3);
	cout << Ret1 << endl;
	TestDelegate.UnBind();

但是我们为了更贴近UE的方式,所以使用类似的定义方式

#define DEFINE_SIMPLE_SINGLE_DELEGATE(Name,Return,...) class Name : public FSingleDelegate<Return,__VA_ARGS__>{}

之后我们声明

DEFINE_SIMPLE_SINGLE_DELEGATE(MyTestDelegate, int, int, int);

如下的使用方式简介清晰了很多

	MyTestDelegate TestDel;
	TestDel.Bind([](int a, int b)->int
		{
			return a + b;
		});
	int Ret2 = TestDel.Execute(3, 4);
	cout << Ret2 << endl;
	TestDel.UnBind();

完善多播

有了上面单播的例子,我们多播只需要一个容器来存储多个即可,所以我们使用Map容器(为了之后能对某一个函数进行移除操作)

#include <map>
typedef void* DelegateHandle;
template<typename TReturn, typename ...InParams>
class FMulDelegate : public std::map<DelegateHandle,FDelegate<TReturn, InParams...>>
{
	typedef FDelegate<TReturn, InParams...> DelegateType;
public:
	FMulDelegate()
	{
	}

	template<typename TObjectInstance>
	DelegateHandle Bind(TObjectInstance* InObjectInstance, TReturn(TObjectInstance::* InObjectFunction)(InParams...))
	{
		DelegateHandle Handle = reinterpret_cast<void*&>(InObjectFunction);
		this->insert(make_pair(Handle,DelegateType()));
		DelegateType& Del =(*this)[Handle];
		Del.Bind(InObjectInstance, InObjectFunction);

		return nullptr;
	}

	DelegateHandle Bind(TReturn(*InObjectFunction)(InParams...))
	{
		DelegateHandle Handle = InObjectFunction;
		this->insert(make_pair(Handle, DelegateType()));
		DelegateType& Del = (*this)[Handle];
		Del.Bind(InObjectFunction);

		return Handle;
	}

	void Broadcast(InParams &&...Params)
	{
		for (auto& item : *this)
		{
			item.second.Execute(forward<InParams>(Params)...);
		}
	}

	void UnBind(DelegateHandle Handle)
	{
		DelegateType& Del = (*this)[Handle];
		Del.UnBind();
		this->erase(Handle);
	}

	void UnBindAll()
	{
		for (auto& item : *this)
		{
			item.second.UnBind();
		}
		this->clear();
	}

};
#define DEFINE_SIMPLE_MUL_DELEGATE(Name,...) class Name : public FMulDelegate<void,__VA_ARGS__>{}
DEFINE_SIMPLE_MUL_DELEGATE(MyTestMulDelegate, int, int);

使用:

	struct FMyStruct
	{
		void TestFunc(int a, int b)
		{
			cout << a * b << endl;
		}
	};
	MyTestMulDelegate TestMulDel;
	DelegateHandle h1 = TestMulDel.Bind([](int a1, int a2)
		{
			cout << a1 + a2 << endl;
		});
	FMyStruct myStruct;
	TestMulDel.Bind(&myStruct, &FMyStruct::TestFunc);


	TestMulDel.UnBind(h1);
	TestMulDel.Broadcast(2, 3);
	TestMulDel.UnBindAll();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值