UE4/UE5 代理使用介绍[通俗易懂]

UE4/UE5 代理使用介绍[通俗易懂]原创文章,转载请注明出处。UE4有一套代理机制,整理了一下做个介绍。也请大家做补充。有了代理,方便我们做代码设计,减轻耦合。文章里面的代码下载链接:代理单播代理二级目录三级目录多播代理二级目录三级目录单播代理二级目录三级目录多播代理二级目录三级目录…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

原创文章,转载请注明出处。

## 今晚北京时间晚10点,虚幻官方发布UE5,内心是五笔的机动。

UE4有一套代理机制,整理了一下做个介绍。也请大家做补充。
有了代理,方便我们做代码设计,减轻耦合。

由于下面没有贴出全部代码,如果粘贴过去测试的话编译不过。所以我上传了一下,下载后对照更加一目了然。下载链接
针对不同的绑定我写了不同的类来演示。
文章介绍的目录比较深,不过也相对介绍全了用法。

代理汇总

文章里面的代码下载链接:

1>DelegateCombinations.h主要是代理的定义,这里头定义了
单播/多播/动态单播/动态多播/事件

的所有用法

2>Engine里面的CoreDelegates.h里面是一些引擎使用代理的地方,可以参考

3>如果你想做在代码里面被多处接收更新的,就用多播。这个也是GamePlay里面最多被用到的

4>如果你想和UMG控件/Component组件在蓝图右下角中可以添加事件的,就用动态多播

5>如果你想设计的漂亮,写个接口,用Event,但是不能被蓝图使用

一.单播,不支持蓝图

单播:顾名思义就是一次广播,只能通知到一个回调函数。
可以有返回值。如果重复调用绑定,将使用最后一个绑定的函数作为回调函数。

1.单播种类

1>无参数&无返回值

//(0参数)
DECLAR1E_DELEGATE(FDelegateSingleParm0);

2>无参数&有返回值

//(0参数, 有返回值类型为int32, 先写返回值, 在写代理名称)
DECLARE_DELEGATE_RetVal(int32, FDelegateSingleParm0WithRet);

3>1-9个参数&无返回值

//1参数, 参数写代理名称后头
DECLARE_DELEGATE_OneParam(FDelegateSingleParm1, int32);
//2参数, 3参数, 4参数 依次类推, 最多到9个参数
//……

//9个参数的
DECLARE_DELEGATE_NineParams(FDelegateSingleParm9, int32, int32, int32, int32, int32, int32, int32, int32, int32);

4>1-9个参数&有返回值

//1参数, 参数写代理名称后头
DECLARE_DELEGATE_RetVal_OneParam(int32, FDelegateSingleParm1WithRet, int32);

//2参数, 3参数, 4参数 依次类推, 最多到9个参数
//……

//9个参数的
DECLARE_DELEGATE_RetVal_NineParams(int32, FDelegateSingleParm9WithRet, int32, int32, int32, int32, int32, int32, int32, int32, int32);

2.单播使用

1>单播使用->定义

//单播(也就是只能绑定一个函数)
//(0参数)
DECLARE_DELEGATE(FDelegateSingleParm0);
//(0参数, 有返回值类型为int32, 先写返回值, 在写代理名称)
DECLARE_DELEGATE_RetVal(int32, FDelegateSingleParm0WithRet);

//1参数, 参数写代理名称后头
DECLARE_DELEGATE_OneParam(FDelegateSingleParm1, int32);
DECLARE_DELEGATE_RetVal_OneParam(int32, FDelegateSingleParm1WithRet, int32);

//2参数, 3参数, 4参数 依次类推, 最多到9个参数
//……

//9个参数的
DECLARE_DELEGATE_NineParams(FDelegateSingleParm9, int32, int32, int32, int32, int32, int32, int32, int32, int32);
DECLARE_DELEGATE_RetVal_NineParams(int32, FDelegateSingleParm9WithRet, int32, int32, int32, int32, int32, int32, int32, int32, int32);


static FDelegateSingleParm0 DelegateSingleParm0;
static FDelegateSingleParm0WithRet DelegateSingleParm0WithRet;
static FDelegateSingleParm1 DelegateSingleParm1;
static FDelegateSingleParm1WithRet DelegateSingleParm1WithRet;
static FDelegateSingleParm9 DelegateSingleParm9;
static FDelegateSingleParm9WithRet DelegateSingleParm9WithRet;

2>单播使用->绑定

单播使用->绑定->BindLambda Lambda表达式

void ExcuteSingleParm0Lamdba()
{ 
   
	UUtilsLibrary::Log(TEXT("ExcuteSingleParm0Lamdba"));
}
int32 ExcuteSingleParm0WithRetLambda()
{ 
   
	UUtilsLibrary::Log(TEXT("ExcuteSingleParm0WithRetLambda"));
	return 1;
}

//绑定Lambda表达式
FTestDelegates::DelegateSingleParm0.BindLambda([this]() { 
    ExcuteSingleParm0Lamdba(); });
FTestDelegates::DelegateSingleParm0WithRet.BindLambda([this]() { 
    return ExcuteSingleParm0WithRetLambda(); });

单播使用->绑定->BindWeakLambda Lambda表达式

BindWeakLambda 方法需要要在UObject类中使用,非继承自U类的是不能使用的。绑定Lambda表达式并且是持有UObject对象的弱引用

//这个方法我是写到继承自U类的方法里面的
FTestDelegates::DelegateSingleParm0.BindWeakLambda(this, [this]() { 
    OnExcuteSingleParm0Lamdba(); });

单播使用->绑定->BindRaw 原生C++函数

FTestDelegates::DelegateSingleParm0.BindRaw(this, &CTestRaw::ExcuteSingleParm0);
//FTestDelegates::DelegateSingleParm0.BindRaw(this, &CTestRaw::ExcuteSingleParm01111); //重复绑定会用最后的函数
FTestDelegates::DelegateSingleParm0.BindStatic(&hhh12312312);							//重复绑定会用最后的函数
FTestDelegates::DelegateSingleParm0WithRet.BindRaw(this, &CTestRaw::ExcuteSingleParm0WithRet);
FTestDelegates::DelegateSingleParm1.BindRaw(this, &CTestRaw::ExcuteSingleParm1);
FTestDelegates::DelegateSingleParm1WithRet.BindRaw(this, &CTestRaw::ExcuteSingleParm1WithRet);
FTestDelegates::DelegateSingleParm9.BindRaw(this, &CTestRaw::ExcuteSingleParm9);
FTestDelegates::DelegateSingleParm9WithRet.BindRaw(this, &CTestRaw::ExcuteSingleParm9WithRet);

单播使用->绑定->BindSP 智能指针函数(非线程安全版本,Fast模式版本)

我这个里面的测试代码,文章开头有链接可以提供下载,可以直接下载下来看更直观。
注意类的书写方式,继承自public TSharedFromThis<CTestNotSafeSharePoint, ESPMode::Fast>

//测试单播绑定智能指针,FastMode, 非线程安全版本
class CTestNotSafeSharePoint : public TSharedFromThis<CTestNotSafeSharePoint, ESPMode::Fast>
{ 
   
}
//绑定智能指针,FastMode, 非线程安全
FTestDelegates::DelegateSingleParm0.BindSP(this, &CTestNotSafeSharePoint::ExcuteSingleParm0);
FTestDelegates::DelegateSingleParm0WithRet.BindSP(this, &CTestNotSafeSharePoint::ExcuteSingleParm0WithRet);
FTestDelegates::DelegateSingleParm1.BindSP(this, &CTestNotSafeSharePoint::ExcuteSingleParm1);
FTestDelegates::DelegateSingleParm1WithRet.BindSP(this, &CTestNotSafeSharePoint::ExcuteSingleParm1WithRet);
FTestDelegates::DelegateSingleParm9.BindSP(this, &CTestNotSafeSharePoint::ExcuteSingleParm9);
FTestDelegates::DelegateSingleParm9WithRet.BindSP(this, &CTestNotSafeSharePoint::ExcuteSingleParm9WithRet);

单播使用->绑定->BindThreadSafeSP 智能指针函数(线程安全版本,Safe)

//注意类的书写方式,继承自public TSharedFromThis<CTestNotSafeSharePoint, ESPMode::ThreadSafe>

//测试单播绑定智能指针,ThreadSafe, 线程安全版本
class CTestSafeSharePoint : public TSharedFromThis<CTestSafeSharePoint, ESPMode::ThreadSafe>
{ 
   
};
//绑定智能指针,ThreadSafe,线程安全版本
FTestDelegates::DelegateSingleParm0.BindThreadSafeSP(this, &CTestSafeSharePoint::ExcuteSingleParm0);
FTestDelegates::DelegateSingleParm0WithRet.BindThreadSafeSP(this, &CTestSafeSharePoint::ExcuteSingleParm0WithRet);
FTestDelegates::DelegateSingleParm1.BindThreadSafeSP(this, &CTestSafeSharePoint::ExcuteSingleParm1);
FTestDelegates::DelegateSingleParm1WithRet.BindThreadSafeSP(this, &CTestSafeSharePoint::ExcuteSingleParm1WithRet);
FTestDelegates::DelegateSingleParm9.BindThreadSafeSP(this, &CTestSafeSharePoint::ExcuteSingleParm9);
FTestDelegates::DelegateSingleParm9WithRet.BindThreadSafeSP(this, &CTestSafeSharePoint::ExcuteSingleParm9WithRet);

单播使用->绑定->BindStatic 静态方法

//用来测试的静态函数
static void MyTestStaticFunc()
{ 
   
	UUtilsLibrary::Log(TEXT("static function MyTestStaticFunc"));
}
FTestDelegates::DelegateSingleParm0.BindStatic(&MyTestStaticFunc);

单播使用->绑定->BindUFunction UFUNCTION()修饰的函数

注意,你的方法一定是要被UFUNCTION()所修饰的

//this, 字符串(函数名称)
FTestDelegates::DelegateSingleParm1.BindUFunction(this, "OnExcuteSingleParm1");
FTestDelegates::DelegateSingleParm1WithRet.BindUFunction(this, "OnExcuteSingleParm1WithRet");

单播使用->绑定->BindUObject UObject类的函数

顾名思义,就是我们这个方法要定义在U类的派生类上。不需要加UFUNCTION()标记

//BindUObject测试
FTestDelegates::DelegateSingleParm0.BindUObject(this, &AMyDelegateTestActor::OnExcuteSingleParm0);
FTestDelegates::DelegateSingleParm0WithRet.BindUObject(this, &AMyDelegateTestActor::OnExcuteSingleParm0WithRet);

3>单播使用->执行

void MyExecue()
{ 
   
	int32 nParam = 1;
	int32 nRet = 2;

	FTestDelegates::DelegateSingleParm0.ExecuteIfBound();
	if (FTestDelegates::DelegateSingleParm0WithRet.IsBound())
		nRet = FTestDelegates::DelegateSingleParm0WithRet.Execute();

	FTestDelegates::DelegateSingleParm1.ExecuteIfBound(nParam);
	if (FTestDelegates::DelegateSingleParm1WithRet.IsBound())
		nRet = FTestDelegates::DelegateSingleParm1WithRet.Execute(nParam);

	FTestDelegates::DelegateSingleParm9.ExecuteIfBound(nParam, nParam, nParam, nParam, nParam, nParam, nParam, nParam, nParam);
	if (FTestDelegates::DelegateSingleParm9WithRet.IsBound())
		nRet = FTestDelegates::DelegateSingleParm9WithRet.Execute(nParam, nParam, nParam, nParam, nParam, nParam, nParam, nParam, nParam);
}

4>单播使用->解绑

void CanelBind()
{ 
   
	FTestDelegates::DelegateSingleParm0.Unbind();
	FTestDelegates::DelegateSingleParm0WithRet.Unbind();
	FTestDelegates::DelegateSingleParm1.Unbind();
	FTestDelegates::DelegateSingleParm1WithRet.Unbind();
	FTestDelegates::DelegateSingleParm9.Unbind();
	FTestDelegates::DelegateSingleParm9WithRet.Unbind();
}

二.多播,不支持蓝图

单播:顾名思义就是一次广播,通知到多个回调函数上。
和单播不同,多播是没有返回值的。
多播每次绑定的函数都会在广播的时候进行调用,所以也要注意不要重复绑定, 用好解绑和绑定方法。

1.多播种类

1>无参数

//不带参数的多播
DECLARE_MULTICAST_DELEGATE(FDelegateMulticastNoParam);

2>1-9参数

//带有1个参数的多播
DECLARE_MULTICAST_DELEGATE_OneParam(FDelegateMulticastParam1, int32);
///...2-8个参数的可以自己写一下
//带有9个参数的多播
DECLARE_MULTICAST_DELEGATE_NineParams(FDelegateMulticastParam9, int32, int32, int32, int32, int32, int32, int32, int32, int32);

2.多播使用

1>多播使用->定义

//不带参数的多播
DECLARE_MULTICAST_DELEGATE(FDelegateMulticastNoParam);
//带有1个参数的多播
DECLARE_MULTICAST_DELEGATE_OneParam(FDelegateMulticastParam1, int32);
///...2-8个参数的可以自己写一下
//带有9个参数的多播
DECLARE_MULTICAST_DELEGATE_NineParams(FDelegateMulticastParam9, int32, int32, int32, int32, int32, int32, int32, int32, int32);

static FDelegateMulticastNoParam DelegateMulticastNoParam;
static FDelegateMulticastParam1 DelegateMulticastParam1;
static FDelegateMulticastParam9 DelegateMulticastParam9;

2>多播使用->绑定

和单播的方法是类似的,区别就是单播叫Bind,多播叫Add,也很容易理解。多播是支持多个回调广播的。

多播使用->绑定->AddLambda Lambda表达式

FTestDelegates::DelegateMulticastNoParam.AddLambda([this]() { OnExcuteSingleParm0Lamdba(); });

多播使用->绑定->AddWeakLambda Lambda表达式

AddWeakLambda 方法需要要在UObject类中使用,非继承自U类的是不能使用的。绑定Lambda表达式并且是持有UObject对象的弱引用

FTestDelegates::DelegateMulticastNoParam.AddWeakLambda(this, [this]() { OnExcuteSingleParm0Lamdba(); });

多播使用->绑定->AddRaw 原生C++函数

FTestDelegates::DelegateMulticastNoParam.AddRaw

多播使用->绑定->AddSP 智能指针函数(非线程安全版本,Fast模式版本)

FTestDelegates::DelegateMulticastNoParam.AddSP

多播使用->绑定->AddThreadSafeSP 智能指针函数(线程安全版本,Safe)

FTestDelegates::DelegateMulticastNoParam.AddThreadSafeSP

多播使用->绑定->AddStatic 静态方法

FTestDelegates::DelegateMulticastNoParam.AddStatic

多播使用->绑定->AddUFunction UFUNCTION()修饰的函数

FTestDelegates::DelegateMulticastNoParam.AddUFunction

注意,你的方法一定是要被UFUNCTION()所修饰的

多播使用->绑定->AddUObject UObject类的函数

FTestDelegates::DelegateMulticastNoParam.AddUObject

3>多播使用->执行

调用Broadcast

FTestDelegates::DelegateMulticastNoParam.Broadcast(/*your params here*/);

4>多播使用->解绑

单个解绑、整体解绑。
比如在类中使用的时候,如在A类里面使用的时候,建议在Beginplay等方法开始绑定,在EndPlay解除绑定。

//多播绑定
FDelegateHandle m_Delegate1 = FTestDelegates::DelegateMulticastNoParam.AddLambda([this]() { 
    OnExcuteSingleParm0Lamdba(); });
FDelegateHandle m_Delegate2 = FTestDelegates::DelegateMulticastNoParam.AddWeakLambda(this, [this]() { 
    OnExcuteSingleParm0Lamdba(); });

//多播解绑->单个函数解绑
FTestDelegates::DelegateMulticastNoParam.Remove(m_Delegate1);
FTestDelegates::DelegateMulticastNoParam.Remove(m_Delegate2);

//全部解绑
FTestDelegates::DelegateMulticastNoParam.Clear();

三.动态单播,不支持蓝图

单播:顾名思义就是一次广播,只能通知到一个回调函数。
1>Notes:可以有返回值。如果重复调用绑定,将使用最后一个绑定的函数作为回调函数。
2>Notes:被绑定函数必须要有UFUNCTION()修饰,否则会崩溃
3>Notes:必须要写在序列化的文件里面, 也就是.generated.h的文件中
4>Notes:因为支持序列化,所以参数名字也要写上,不同于上面的非动态代理只需要定义类型即可,这个还需要定义好参数名称

1.动态单播种类

1>无参数&无返回值

//(0参数)
DECLARE_DYNAMIC_DELEGATE(FDelegateDynamicSingleNoParam);

2>无参数&有返回值

//(0参数, 有返回值类型为int32, 先写返回值, 在写代理名称)
DECLARE_DYNAMIC_DELEGATE_RetVal(int32, FDelegateDynamicSingleNoParamWithRet);

3>1-9个参数&无返回值

//1参数, 参数写代理名称后头
DECLARE_DYNAMIC_DELEGATE_OneParam(FDelegateDynamicSingleParm1, int32, param1);
//2参数, 3参数, 4参数 依次类推, 最多到9个参数
//……
//9个参数的
DECLARE_DYNAMIC_DELEGATE_NineParams(FDelegateDynamicSingleParm9, int32, param1, int32, param2, int32, param3, int32, param4, int32, param5, int32, param6, int32, param7, int32, param8, int32, param9);

4>1-9个参数&有返回值

//1参数, 参数写代理名称后头
DECLARE_DYNAMIC_DELEGATE_RetVal_OneParam(int32, FDelegateDynamicSingleParm1WithRet, int32, param1);
//2参数, 3参数, 4参数 依次类推, 最多到9个参数
//……
//9个参数的
DECLARE_DYNAMIC_DELEGATE_RetVal_NineParams(int32, FDelegateDynamicSingleParm9WithRet, int32, param1, int32, param2, int32, param3, int32, param4, int32, param5, int32, param6, int32, param7, int32, param8, int32, param9);

2.动态单播使用

1>动态单播使用->定义

具体写法参考上面单播就行

DECLARE_DYNAMIC_DELEGATE(FDelegateDynamicSingleNoParam);
//1参数, 参数写代理名称后头
DECLARE_DYNAMIC_DELEGATE_OneParam(FDelegateDynamicSingleParm1, int32, param1);
//2参数, 3参数, 4参数 依次类推, 最多到9个参数
//……
//9个参数的
DECLARE_DYNAMIC_DELEGATE_NineParams(FDelegateDynamicSingleParm9, int32, param1, int32, param2, int32, param3, int32, param4, int32, param5, int32, param6, int32, param7, int32, param8, int32, param9);


FDelegateDynamicSingleNoParam DelegateDynamicSingleNoParam;
FDelegateDynamicSingleNoParamWithRet DelegateDynamicSingleNoParamWithRet;

2>动态单播使用->绑定

动态单播使用->绑定->BindBindDynamic

调用BindBindDynamic进行绑定即可,并且记住绑定的函数一定是有UFUNCTION()修饰的.
后绑定会覆盖前面的绑定,因为是单播

DelegateDynamicSingleNoParam.BindDynamic(this, &AMyDelegateTestActor::FuncDelegateDynamicSingleNoParam);

3>动态单播使用->执行

调用ExecuteIfBound比较安全,如果直接调用Execute没有绑定的话会引发断言崩溃。

DelegateDynamicSingleNoParam.ExecuteIfBound();

4>动态单播使用->解绑

直接调用.Clear()清除绑定

DelegateDynamicSingleNoParam.Clear();

四.动态多播,支持蓝图使用

‘BlueprintAssignable’ is only allowed on multicast delegate properties
‘BlueprintAssignable’只允许在多播委托属性上使用

单播:顾名思义就是一次广播,通知到多个回调函数上。
和动态单播不同,动态多播是没有返回值的。
像UMG控件还有很多组件在蓝图中右下角可以添加事件,就是通过这个动态多播实现的
函数必须强制加UFUNCTION()宏, 否则运行时会报错 引发断言崩溃掉
动态多播每次绑定的函数都会在广播的时候进行调用,所以也要注意不要重复绑定, 用好解绑和绑定方法。

1.动态多播种类

1>无参数

//不带参数的多播
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDelegateDynamicMulticastNoParam);

2>1-9参数

//带有1个参数的多播
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDelegateDynamicMulticastParam1, int32, param1);
//中间省略2-8个参数的多播
//带有9个参数的多播
DECLARE_DYNAMIC_MULTICAST_DELEGATE_NineParams(FDelegateDynamicMulticastParam9, int32, param1, int32, param2, int32, param3, int32, param4, int32, param5, int32, param6, int32, param7, int32, param8, int32, param9);

2.动态多播使用

1>动态多播使用->定义

//不带参数的多播
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDelegateDynamicMulticastNoParam);
//带有1个参数的多播
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDelegateDynamicMulticastParam1, int32, param1);
//中间省略2-8个参数的多播
//带有9个参数的多播
DECLARE_DYNAMIC_MULTICAST_DELEGATE_NineParams(FDelegateDynamicMulticastParam9, int32, param1, int32, param2, int32, param3, int32, param4, int32, param5, int32, param6, int32, param7, int32, param8, int32, param9);

FDelegateDynamicMulticastNoParam DelegateDynamicMulticastNoParam;
FDelegateDynamicMulticastParam1 DelegateDynamicMulticastParam1;
FDelegateDynamicMulticastParam9 DelegateDynamicMulticastParam9;

2>动态多播使用->绑定

和动态单播的方法是类似的,区别就是单播叫Bind,多播叫Add,也很容易理解。多播是支持多个回调广播的。

动态多播使用->绑定->AddDynamic

DelegateDynamicMulticastNoParam.AddDynamic(this, &AMyDelegateTestActor::FuncDelegateDynamicMulticastNoParam);
DelegateDynamicMulticastNoParam.AddDynamic(this, &AMyDelegateTestActor::FuncDelegateDynamicMulticastNoParam2);

3>动态多播使用->执行

调用Broadcast

DelegateDynamicMulticastNoParam.Broadcast(/*your params here*/);

4>多播使用->解绑

//方式1 清空所有绑定

DelegateDynamicMulticastNoParam.Clear();

//方式2 清空单个,按函数地址

DelegateDynamicMulticastNoParam.RemoveDynamic(this, &AMyDelegateTestActor::FuncDelegateDynamicMulticastNoParam2);

//方式3 清空单个, 按字符串

DelegateDynamicMulticastNoParam.Remove(this, TEXT("FuncDelegateDynamicMulticastNoParam"));

五.事件, 可多态,不支持蓝图使用

** 不允许写在A类里面**
** 允许写在U类里面和F类里面**
** 和多播一样,可以绑定多个回调函数**
** 多态关键字 DECLARE_DERIVED_EVENT***
事件,绑定用法和单播一样,但是它可以进行多播。并且可以设计成可被继承的代理,引擎里面有很多地方都在这么使用。

介绍一下如何实现事件的继承
** DECLARE_DERIVED_EVENT***

1.Event事件种类

DECLARE_EVENT 无参数
DECLARE_EVENT_OneParam 1个参数
//2-8个参数的就不一一列出来了,去DelegateCombinations.h中查阅
DECLARE_EVENT_NineParams 9个参数

2.Event事件使用

1>Event事件使用->定义

首先,我做了一个接口类,方法是纯虚函数,然后在我的F类里面做继承测试(也可以是U类,但是不可以是带有反射信息的A类)
//第一个参数:属于的类名
//第二个参数:Event名称
//后续的参数:就是填的params了
DECLARE_EVENT(IMyEvents, FMySocketConnectedEvent);
…………

//用来演示代理里面Event的继承
//用来演示代理里面Event的继承
class IMyEvents
{ 
   
public:

	virtual ~IMyEvents()
	{ 
    }

	DECLARE_EVENT_OneParam(IMyEvents, FMySocketMessageEvent, const FString& /* MessageString */);
	virtual FMySocketMessageEvent& OnMessage() = 0;
};

下面是继承类实现


//Event测试类
class CTestEvent : public IMyEvents, public TSharedFromThis<CTestEvent, ESPMode::ThreadSafe>
{ 
   
public:
	//Events测试

	void OnExcuteEventCTestEventOnRawMessage(const FString&)
	{ 
   
		UUtilsLibrary::Log(TEXT("Safe SharePoint OnExcuteEventCTestEventOnRawMessage"));
	}

	DECLARE_DERIVED_EVENT(FLwsMySocket, IMyEvents::FMySocketMessageEvent, FMySocketMessageEvent);
	virtual FMySocketMessageEvent& OnMessage() override
	{ 
   
		return MessageEvent;
	}

	FMySocketMessageEvent MessageEvent;


	void BindAndExcute()
	{ 
   
		//OnMessage().AddLambda
		//OnMessage().AddRaw
		//OnMessage().AddSP
		//OnMessage().AddStatic
		//OnMessage().AddThreadSafeSP
		//OnMessage().AddUFunction
		//OnMessage().AddUObject
		//OnMessage().AddWeakLambda
		m_Delegate1 = OnMessage().AddThreadSafeSP(this, &CTestEvent::OnExcuteEventCTestEventOnRawMessage);
		OnMessage().AddThreadSafeSP(this, &CTestEvent::OnExcuteEventCTestEventOnRawMessage);
		OnMessage().AddThreadSafeSP(this, &CTestEvent::OnExcuteEventCTestEventOnRawMessage);
		OnMessage().Broadcast(TEXT("test event"));
	}
	void CanelBind()
	{ 
   
		OnMessage().Clear();
		OnMessage().Remove(m_Delegate1);
		//OnMessage().RemoveAll()
	}
	~CTestEvent()
	{ 
   
		CanelBind();
	}
	FDelegateHandle m_Delegate1;
};

2>Event事件使用->绑定

//OnMessage().AddLambda
//OnMessage().AddRaw
//OnMessage().AddSP
//OnMessage().AddStatic
//OnMessage().AddThreadSafeSP
//OnMessage().AddUFunction
//OnMessage().AddUObject
//OnMessage().AddWeakLambda
OnMessage().AddThreadSafeSP(this, &CTestEvent::OnExcuteEventCTestEventOnRawMessage);
OnMessage().AddThreadSafeSP(this, &CTestEvent::OnExcuteEventCTestEventOnRawMessage);
OnMessage().AddThreadSafeSP(this, &CTestEvent::OnExcuteEventCTestEventOnRawMessage);

3>Event事件使用->执行

调用Broadcast

MessageEvent.Broadcast(TEXT("test event"));

4>Event事件使用->解绑

//第一种方式 清空全部绑定

OnMessage().Clear();

//第二种方式 清空单个绑定

m_Delegate1 = OnMessage().AddThreadSafeSP(this, &CTestEvent::OnExcuteEventCTestEventOnRawMessage);
OnMessage().Remove(m_Delegate1);

第三种方式

OnMessage().RemoveAll()

谢谢,创作不易,大侠请留步… 动起可爱的双手,来个赞再走呗 <( ̄︶ ̄)>

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/188191.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • getParameterValues用法

    getParameterValues用法getParameterValues用法你希望学习哪些程式语言:JSP  PHP  PERL    这些inputtype名称都叫做langtype,如果用request.getParameter(“langtype”)来取这些值,到底要取哪一个?所以在这个时候,不能用getParameter来取资料,而应该用getParameterValues来取资

    2022年7月22日
    9
  • WMI远程访问问题解决方法

    WMI远程访问问题解决方法

    2021年8月4日
    52
  • According to TLD or attribute directive in tag file, attribute value does not accept any expressions

    According to TLD or attribute directive in tag file, attribute value does not accept any expressions

    2022年1月30日
    32
  • 游戏开发学习路线

    游戏开发学习路线当你在吃鸡,王者农药的时候是否有想过如何才能做出一款这样让人神迷的游戏?游戏开发这个方向看起来目标很明确,但其实是个领域很广的方向,入门的时候如果得不到指点一二,很容易误入歧途,相反,如果走这条路之前能得到前人的一些指引,是可以事半功倍的。下面就结合自己的学习历程和大家分享下游戏开发的学习路线。1.介绍游戏开发分为客户端和服务端两条不同的路线,路线不同,所需的技能也不同。但有些…

    2022年4月19日
    79
  • lte频谱带宽_lte信道带宽可以配置为

    lte频谱带宽_lte信道带宽可以配置为1.频带(Band)所谓频带,指代的是一个频率的范围或者频谱的宽度,即无线解码器的最低工作频率至最高工作频率之间的范围,单位是Hz。为了方便起见,在LTE中,使用数字1-43来表示不同的频带(36101-V10.21.0版本协议),从而指代不同的频率范围。协议36101规定了目前LTE所有的频带、该频带的频率范围和LTE制式,如下图所示。需要注意的是,频带1-32的上下行频率范围是不重叠的,即上行

    2022年10月11日
    2
  • 关于颜色的十六进制对照表图片_84的十六进制

    关于颜色的十六进制对照表图片_84的十六进制关于颜色的十六进制对照表便于查找ctrl+F调色板文字查找颜色英文代码形象描述十六进制RGBLightPink浅粉红#FFB6C1255,182,193Pink粉红#

    2022年8月6日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号