代理允许您在C++对象上以通用的但类型安全的方式调用成员函数。通过使用代理,可以将其动态地绑定到任何对象的成员函数上,然后在该对象上调用函数,即时调用者不知道该对象的类型也没关系。

任何时候都应该通过引用传递代理。

声明代理

通过使用以下提供的任何一个宏都可以声明代理。所使用的宏由要绑定到该代理上的函数的签名决定。系统预定义了各种通用函数签名的组合、可以根据这些组合声明代理类型、给返回值及参数填入需要的任何类型的类型名称。现在支持使用以下任何条件组合的代理签名:

  • 返回一个值的函数

  • 多达4个"负载" 变量

  • 多达8个函数参数

  • 声明为 'const'的函数

 

函数签名

声明宏

void Function()

DECLARE_DELEGATE( DelegateName )

void Function( <Param1> )

DECLARE_DELEGATE_OneParam( DelegateName, Param1Type )

void Function( <Param1>, <Param2> )

DECLARE_DELEGATE_TwoParams( DelegateName, Param1Type, Param2Type )

void Function( <Param1>, <Param2>, ... )

DECLARE_DELEGATE_<Num>Params( DelegateName, Param1Type, Param2Type, ... )

<RetVal> Function()

DECLARE_DELEGATE_RetVal( RetValType, DelegateName )

<RetVal> Function( <Param1> )

DECLARE_DELEGATE_RetVal_OneParam( RetValType, DelegateName, Param1Type )

<RetVal> Function( <Param1>, <Param2> )

DECLARE_DELEGATE_RetVal_TwoParams( RetValType, DelegateName, Param1Type, Param2Type )

<RetVal> Function( <Param1>, <Param2>, ... )

DECLARE_DELEGATE_RetVal_<Num>Params( RetValType, DelegateName, Param1Type, Param2Type, ... )

绑定代理

代理系统理解某些对象类型,且当使用这些对象时会启用附加功能。如果您把一个代理绑定到一个UObject或共享的指针类上,代理系统可以保持一个到该对象的弱引用,以便当该对象在该代理的底层被销毁了时,您可以通过调用 IsBound() 或 ExecuteIfBound() 函数处理这些情况。注意,所支持的各种对象类型有特定的绑定语法。

 

函数

描述

Bind()

绑定到一个现有的代理对象上。

BindRaw()

绑定到一个原始的C++指针全局函数代理上。原始指针不使用任何引用,所以如果从代理的底层删除了该对象,那么调用它可能是不安全的。因此,当调用Execute()时一定要小心!

BindSP()

绑定一个基于共享指针的成员函数代理。共享指针代理保持到您的对象的弱引用。您可以使用 ExecuteIfBound() 来调用它们。

BindUObject()

绑定一个基于UObject的成员函数代理。UObject 代理保持到您的对象的弱引用。您可以使用 ExecuteIfBound() 来调用它们。

UnBind()

解除绑定该代理。

例如我在项目中遇到的:

GM->SPState->UpdateStateWidget.BindRaw(GameHUDWidget->PlayerStateWidget.Get(), &SSIAiPlayerStateWidget::UpdateStateWidget);

PlayerStateWidget继承自SWidget

ShortcutWidget->RegisterShortCutContainer.BindUObject(GM->SPState,&ASIAiPlayerState::RegisterShortCutContainer);

SPState为APlayerState子类,最终继承自UObject,所以使用BindUObject

执行代理

绑定到代理上的函数可以通过调用代理的 Execute() 函数进行执行。在执行这些函数之前必须检查是否已经“绑定”了代理。这是为了使得代码更加安全,因为可能代理有时会具有未初始化且后续要访问的返回值及输出参数。执行一个未绑定的代理实际上有时会扰乱内存。可以调用 IsBound() 来判断执行该代理是否安全。同时,对于没有返回值的代理,您可以调用 ExecuteIfBound() 函数,但是一定要注意那些可能未初始化的输出参数。

 

执行函数

描述

Execute()

 

ExecuteIfBound()

 

IsBound()

UE4 代理 BindRaw和BindUObject的更多相关文章

  1. [UE4]代理事件(C++)

    用宏定义类似格式: DECLARE_DELEGATE //普通代理 DECLARE_DYNAMIC_DELEGATE_TwoParams //动态代理 DECLARE_DYNAMIC_MULTICAS ...

  2. UEC++ 代理/委托

    代理: 代理可以帮助我们解决一对一或是一对多的任务分配工作.主要可以帮助我们解决通知问题.我们可以通过代理完成调用某一个对象的一个函数,而不直接持有该对象的任何指针. 代理就是为你跑腿送信的,你可以不 ...

  3. [UE4]事件代理,无输出参数,蓝图中不需要绑定

    .h UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName = "LoginSuccess")) void LoginS ...

  4. [UE4]多播代理实例

    .h DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLoginErrorEvent, FString, ErrorMessage); UPROPERTY(B ...

  5. [UE4]多播代理

    1. 第一种 DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FReceiveDelegateEvent, FString, Value1, FString, ...

  6. 全面理解UE4委托

    UE4中的delegate(委托)常用于解耦不同对象之间的关联:委托的触发者不与监听者有直接关联,两者通过委托对象间接地建立联系 监听者通过将响应函数绑定到委托上,使得委托触发时立即收到通知,并进行相 ...

  7. UE4技术总结——委托

    UE4技术总结--委托 目录 UE4技术总结--委托 一.定义 二.用法 2.1 声明与调用委托 2.1.1 单播委托 2.1.1.a 声明 2.1.1.b 绑定 2.1.1.c 执行委托 2.1.1 ...

  8. 【UE4 C++ 基础知识】<8> Delegate 委托

    概念 定义 UE4中的delegate(委托)常用于解耦不同对象之间的关联:委托的触发者不与监听者有直接关联,两者通过委托对象间接地建立联系. 监听者通过将响应函数绑定到委托上,使得委托触发时立即收到 ...

  9. UE4 WCF RestFul 服务器 读取JSON 数据并解析 简单实例

    Note:不知道为什么通过Txt读取的JsonString,如果TXT 不是ANSI编码的话,会报JsonArrayStringToUStruct  Unable to parse. bool UWg ...

随机推荐

  1. 老雷socket编程之认识常用协议

    老雷socket编程之常见网络协议 1.ip IP协议是将多个包交换网络连接起来,它在源地址和目的地址之间传送一种称之为数据包的东西, 它还提供对数据大小的重新组装功能,以适应不同网络对包大小的要求. ...

  2. zphp源码分析(一)

    zphp是一款轻量级的php服务端框架,是swoole官方开发的.可以用来开发web应用和网络服务. 安装: 可以通过composer安装, { "require": { &quo ...

  3. 经典Java笔试面试题

    面向对象编程(OOP) Java是一个支持并发.基于类和面向对象的计算机编程语言.下面列出了面向对象软件开发的优点: 代码开发模块化,更易维护和修改. 代码复用. 增强代码的可靠性和灵活性. 增加代码 ...

  4. Java:synchronized关键字引出的多种锁

    前言 Java 中的 synchronized关键字可以在多线程环境下用来作为线程安全的同步锁.本文不讨论 synchronized 的具体使用,而是研究下synchronized底层的锁机制,以及这 ...

  5. Kafka学习(一)-------- Quickstart

    参考官网:http://kafka.apache.org/quickstart 一.下载Kafka 官网下载地址 http://kafka.apache.org/downloads 截至2019年7月 ...

  6. sql-实现select取行号、分组后在分组内排序、每个分组中的前n条数据

    表结构设计: 实现select取行号 sql局部变量的2种方式 set @name='cm3333f'; select @id:=1; 区别:set 可以用=号赋值,而select 不行,必须使用:= ...

  7. SQL高度优化

      受同事dd之托,优化一条boss看的报表SQL.dd写复杂疑难SQL无数,如何写出优雅的SQL自有一番心得体会.能将一条7表含inner join,left join并含有关联子查询的.返回结果集 ...

  8. 多线程与高并发(四)volatile关键字

    上一篇学习了synchronized的关键字,synchronized是阻塞式同步,在线程竞争激烈的情况下会升级为重量级锁,而volatile是一个轻量级的同步机制. 前面学习了Java的内存模型,知 ...

  9. Codeforces 730A:Toda 2(multiset模拟)

    http://codeforces.com/problemset/problem/730/A 题意:有n个人打天梯,想让这n个人的分数相同,每场比赛必须有2-5个人参赛,参赛的人会降低一分,问一个合理 ...

  10. python中的 == 和 is 的区别

    == 比较的是两边的值 is 比较的是两边的内存地址  通过 id()获取内存地址 小数据池:我们使用过的值存储在小数据池中,供其他数据使用. 小数据池仅限于 数字 和 字符串: 数字的小数池范围  ...