UE4 C++动态绑定函数的几种实现方法
一、基本实现方案
1、使用TFunction以及Lambda表达式
1.1 在DeleClass定义TFunction
TFunction<void(FString)> TFunOne;
//绑定TFunOne的函数
void RegFunOne(TFunction<void(FString)> TargetFun)
{
TFunOne = TargetFun;
//在任何想要的地方实现该方法
TFunOne(FString(“RegFunOne”));
}
1.2 在ReceClass声明并定义要执行的函数
void ReceClass::EchoInfoOne(FString InfoStr)
{
//自己写的Debug函数
Debug(InfoStr,500.f);
}
1.3 在ReceClass将要执行的函数绑定到TFunction
DeleClass::RegFunOne([this](FString InfoStr){ EchoInfoOne(InfoStr);});
1.4 执行流程:
- ReceClass调用DeleClass::RegFunOne,利用lambda生成一个函数指针作为参数传入
- DeleClass执行RegFunOne,将获取到的函数指针赋值给TFunOne,此时TFunOne已经有具体函数实例
- 实现类中特定函数的动态绑定
2、使用无参数委托
2.1 在DeleClass定义接收函数的委托以及绑定函数
//声明一个无参数最简单的静态委托
DECLARE_DELEGATE(FWDE_Single_Zero)
/*
* 绑定其他类中的函数
* @param TarObj 要绑定函数的类的实例
* @param InMethod TarObj中某个类void(FString,int32)函数的指针
*/
template<class UserClss>
void DeleClass::RegFunTwo(UserClass* TarObj,
typenameTMemFunPtrType<false,UserClass,void(FString,int32)>::Type InMethod)
{
//定义一个委托
FWDE_Single_Zero ExeDel;
//将委托绑定到传入的函数中
ExeDel.BindUObject(TarObj,InMethod,FString("RegFunTwo"),54);
//执行委托
ExeDel.ExecuteIfBound();
}
2.2在ReceClass执行绑定函数
void ReceClass::EchoInfoTwo(FString InfoStr,int32 Count)
{
Debug(InfoStr+FString::FromInt(Count),500.0f);
}
DeleClass->RegFunTwo(this,&AFWReceActor::EchoInfoTwo);
2.3 执行流程
- ReceClass调用DeleClass::RegFunTwo,并将自身以及需要绑定的函数传入
- DeleClass定义一个0参数委托,并利用BindUObject绑定RegFunTwo传入的函数
- 执行委托对象
缺点:只能在绑定时传入参数而不是在运行时
3、使用多参数委托(TUObjectMethodDelegate)
3.1 在DeleClass定义接收函数的委托以及绑定函数
//声明一个无参数最简单的静态委托
DECLARE_DELEGATE_TwoParams(FWDE_Single_Two,FString,int32)
template<class UserClss>
void DeleClass::RegFunThree(UserClass* TarObj,
typename FWDE_Single_Two::TUObjectMethodDelegate<UserClass>::FMeshodPtr InMethod)
{
//定义一个委托
FWDE_Single_Two ExeDel;
//将委托绑定到传入的函数中
ExeDel.BindUObject(TarObj,InMethod);
//执行委托
ExeDel.ExecuteIfBound(FString("RegFunThree"),54);
}
3.2 在ReceClass执行绑定函数
void ReceClass::EchoInfoThree(FString InfoStr,int32 Count)
{
Debug(InfoStr+FString::FromInt(Count),500.0f);
}
DeleClass->RegFunTwo(this,&AFWReceActor::EchoInfoThree);
3.3 执行流程
- ReceClass调用DeleClass::RegFunThree,并将自身以及需要绑定的函数传入
- DeleClass定义一个0参数委托,并利用BindUObject绑定RegFunTwo传入的函数
- 执行委托对象
二、用于开发的泛型化
1 利用泛型建立一个统一的接口
1.1 在DeleClass声明并定义泛型接口
template<class DelegateType, class UserClass, typename... VarTypes>
void RegFunFour(UserClass *TarObj,
typename DelegateType::templete TUObjectMethodDelegate<UserClass>::FMethodPtr InMethod,
VarTypes... Vars)
{
FWDE_Single_Zero ExeDel;
ExeDel.BindUObject(TarObj,InMethod,Vars...);
ExeDel.ExecuteIfBound();
}
1.2 在ReceClass中使用该泛型接口
DECLARE_DELEGATE_TwoParams(FTempDele,FString,int32)
/*
* TempDele 确定委托类型
* EchoInfoTwo 要绑定的函数
* Fstring("")/56 传入的参数
*/
DeleClass->RegFunFour<TempDele>(this,&ReceClass::EchoInfoTwo,FString("RegFunFour"),56);
2 利用泛型实现TFunction的扩展
2.1 在DeleClass中声明并定义接口
template<typename RetType,typename... varTypes>
void DeleClass::RegFunFive(TFunction<RetType(VarTypes...)> TarFun)
{
if(TarFun("RegFunFive",78))
Debug("return true",500.f);
}
2.2 在ReceClass中声明并定义接口
bool ReceClass::EchoInfoThree(FString InfoStr,int32 COunt)
{
Debug(InfoStr+FString::FromInt(COunt),500.f);
return true;
}
//调用该接口
DeleClass->RegFunFive<bool,FString,int32>([this](FString InfoStr,int32 Count){
return EchoInfoThree(InfoStr,Count);
});