栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++委托

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++委托

C++ Delegate

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

一.单播代理
template
class Delegatebase{
public:
	virtual retType Execute(paramTypes ...params)=0;
};

//绑定成员函数
template
class DelegateObject :public Delegatebase
{
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 DelegateFunction:public Delegatebase
{
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:"<delegateObj(&objRef,&testobj::RunDelegate);
	delegateObj.Execute(10,"Unreal");

	DelegateFunctiondelegateFunctor(&testfunction);
	delegateFunctor.Execute(50,"Unity");
	return 0;
}

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

使用工厂生产单播代理
template
class Delegate{
public:
	Delegate():delegatePtr(nullptr){};
	template
	Bind(objType* InObj,retType(objType::*InFunc)(paramTypes...))
	{
		checkDelete();
		delegatePtr = new DelegateObject(InObj,InFunc);
	}

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

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

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

private:
	Delegatebase*delegatePtr;
};

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

	Delegatedelegate;
	delegate.Bind(&objRef,&testobj::RunDelegate);
	delegate.Execute(20,"Cocos");

	Delegatedelegate2;
	delegate2.Bind(&testfunction);
	delegate2.Execute(40,"REEngine");

	return 0;
}

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

#define DELEGATE(delegateName,retType,...) DelegatedelegateName;
//测试代码
DELEGATE(test,string,int,const char*);
test.Bind(&testfunction);
test.Execute(40,"REEngine");
二.多播代理

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

#include
template
class MultiCastDelegate{
public:
	typedef Delegate DelegateType;
	MultiCastDelegate(){};

	template
	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> delegateContainer;
};

const char* testFunc01(int val,string str){
	cout<<"testFunc01"<delegate;
	delegate.Add(&testFunc01);
	delegate.Add(&testFunc02);

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

	delegate.BroadCast(10,"Unreal");	
	return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/395956.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号