C++委托

C++ Delegate

​ 使用Delegate(委托)可以起到类之间的解耦操作,具有对象闭包的特性。同时也是UE4C++中经常用到的特性之一,这里为了自己更好的理解写下该篇博文帮助之后复习。

一.单播代理

template<class retType,class ...paramTypes>
class DelegateBase{
public:
	virtual retType Execute(paramTypes ...params)=0;
};

//绑定成员函数
template<class objectType, class retType,class ...paramsType>
class DelegateObject :public DelegateBase<retType, paramsType...>
{
public:
	DelegateObject(objectType* Inobj, retType(objectType::*InFunc)(paramsType...)):objPtr(Inobj), bindFunc(InFunc){}
	virtual retType Execute(paramsType... params) {
		return (objPtr->*bindFunc)(params...);
	}
private:
	objectType* objPtr;
	retType(objectType::* bindFunc)(paramsType...);
};

//绑定普通函数
template<class retType,class ...paramTypes>
class DelegateFunction:public DelegateBase<retType,paramTypes...>
{
public:
	DelegateFunction(retType(*InFunc)(paramTypes...)):bindFunc(InFunc){};
	virtual retType Execute(paramTypes...params){
		return (*bindFunc)(params...);
	}

private:
	retType(*bindFunc)(paramTypes...);
};


struct testobj{
	const char* RunDelegate(int val,string str){
		cout<<"str:"<<str<<endl;
		cout<<"val:"<<val<<endl;
		return str.c_str();
	}
};

string testfunction(int val,const char* str){
	cout<<"str:"<<str<<endl;
	cout<<"val:"<<val<<endl;
	string tempstr(str);
	return tempstr;
}


//测试代码
int main(){
	testobj objRef;
	DelegateObject<testobj,const char*,int,string>delegateObj(&objRef,&testobj::RunDelegate);
	delegateObj.Execute(10,"Unreal");

	DelegateFunction<string,int,const char*>delegateFunctor(&testfunction);
	delegateFunctor.Execute(50,"Unity");
	return 0;
}

​ 使用函数指针来实现对函数的调用,另一种方式是使用std::functionstd::bind结合的方式进行使用,该方法会在之后UE4委托中实现。同时这里的Delegate类都继承了一个基类DelegateBase,是为了之后使用"工厂"来进行Delegate的统一化,即使用一个类就能实现所有运用Delegate的场景,而不是像现在这样,委托成员函数就需要实例化对应绑定成员函数的代理。

使用工厂生产单播代理

template<class retType,class ...paramTypes>
class Delegate{
public:
	Delegate():delegatePtr(nullptr){};
	template<class objType>
	Bind(objType* InObj,retType(objType::*InFunc)(paramTypes...))
	{
		checkDelete();
		delegatePtr = new DelegateObject<objType,retType,paramTypes...>(InObj,InFunc);
	}

	Bind(retType(*InFunc)(paramTypes...))
	{
		checkDelete();
		delegatePtr = new DelegateFunction<retType,paramTypes...>(InFunc);
	}

	void checkDelete(){
		if(delegatePtr){
			delete delegatePtr;
			delegatePtr = nullptr;
		}
	}

	retType Execute(paramTypes... params){
		return delegatePtr->Execute(params...);
	}

private:
	DelegateBase<retType,paramTypes...>*delegatePtr;
};

//测试代码
int main(){
	testobj objRef;

	Delegate<const char*,int,string>delegate;
	delegate.Bind<testobj>(&objRef,&testobj::RunDelegate);
	delegate.Execute(20,"Cocos");

	Delegate<string,int,const char*>delegate2;
	delegate2.Bind(&testfunction);
	delegate2.Execute(40,"REEngine");

	return 0;
}

​ 也可以模仿UE4的写法,使用宏定义对Delegate进行创建:

#define DELEGATE(delegateName,retType,...) Delegate<retType,__VA_ARGS__>delegateName;
//测试代码
DELEGATE(test,string,int,const char*);
test.Bind(&testfunction);
test.Execute(40,"REEngine");

二.多播代理

​ 多播代理可以一次绑定多个函数对象,以广播的形式通知所有代理函数。知道这个特性我们可以写下如下代码(注意:多播代理无法接收返回值):

#include<vector>
template<class retType,class ...paramTypes>
class MultiCastDelegate{
public:
	typedef Delegate<retType,paramTypes...> DelegateType;
	MultiCastDelegate(){};

	template<class objType>
	Add(objType* InObj,retType(objType::*InFunc)(paramTypes...)){
		delegateContainer.push_back(DelegateType());
		DelegateType& InDelegate = delegateContainer.back();
		InDelegate.Bind(InObj,InFunc);
	}

	Add(retType(*InFunc)(paramTypes...)){
		delegateContainer.push_back(DelegateType());
		DelegateType& InDelegate = delegateContainer.back();
		InDelegate.Bind(InFunc);
	}

	BroadCast(paramTypes... params){
		for(auto& elem:delegateContainer){
			elem.Execute(params...);
		}
	}
private:
	vector<Delegate<retType,paramTypes...>> delegateContainer;
};

const char* testFunc01(int val,string str){
	cout<<"testFunc01"<<endl;
	return str.c_str();
}

const char* testFunc02(int val,string str){
	cout<<"testFunc01"<<endl;
	return str.c_str();
}

struct testobj01{
	const char* testobjFunc01(int val,string str){
		cout<<"testobjFunc01"<<endl;
		return str.c_str();
	}
};

struct testobj02{
	const char* testobjFunc02(int val,string str){
		cout<<"testobjFunc02"<<endl;
		return str.c_str();
	}
};
//测试代码
int main(){
	MultiCastDelegate<const char*,int,string>delegate;
	delegate.Add(&testFunc01);
	delegate.Add(&testFunc02);

	testobj01 obj1;
	testobj02 obj2;
	delegate.Add<testobj01>(&obj1,&testobj01::testobjFunc01);
	delegate.Add<testobj02>(&obj2,&testobj02::testobjFunc02);

	delegate.BroadCast(10,"Unreal");	
	return 0;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值