内容纲要

在使用多线程之前,了解委托是必要条件,因为在跨线程调用时会用到它

  • 不适用委托的调用
Object *obj = new Object;
obj -> Function();
  • 使用委托调用
Delegate del;
del.bind(obj, Object::Function);
del.Execute();

总结:不使用委托就是获取到对象的实例,直接进行调用;委托是将方法注册到委托列表中再调用,在调用时不关心实例化的对象是谁~

委托的声明

支持返回值的函数声明为"const"的函数最多4个"负载"变量最多8个函数参数。新版的好像支持9个,这个会随UE4的更新而变化~
负载是绑定委托的时候传参,普通传参是调用时候传的。

  • 无返回值,无参数的声明
DECLARE_DELEGATE(FTestDelegate)
  • 有返回值,无参数的声明
DECLARE_DELEGATE_RetVal(bool, FTestDelegate_Ret);
  • 无返回值,有参数的声明
DECLARE_DELEGATE_OneParam(FTestDelegate_Bool, bool);

声明的位置和 C# 类似,类里面是内部的,类外面是公共的。

绑定委托

FTestDelegate& UDelegateMaker::MakeDelegate(EDelegateType Type)
{
    if(Delegate.IsBound())
    {
        Delegate.Unbind();
    }
    Switch(Type)
    {
        case EDelegateType::Object: //绑定UE4对象,就是继承UE4类的对象
            if(UEObject == nullptr)
            {
                UEObject = NewObject<UDelegateObject>();
            }
            Delegate.BindUObject(UEObject, &UDelegateObject::TestDelegate);
        break;
        case EDelegateType::Lambda:
            Delegate.BindLambda(
                [](void){
                    UE_LOG(LogTemp, Warning, TEXT(_FUNCTION_);
                }
            );
        break;
        case EDelegateType::Raw:    //绑定原始指针,就是不继承UE4的对象
            if(!RawObjectPtr.IsValid())
            {
                RawObjectPtr = MakeShareable(new RawObject);
            }
            Delegate.BindRaw(RawObjectPtr.Get(), &RawObject::DelegateTest);
        break;
        case EDelegateType::SP: //绑定智能指针,会智能释放
            if(!RawObjectPtr.IsValid())
            {
                RawObjectPtr = MakeShareable(new RawObject);
            }
            Delegate.BindSP(RawObjectPtr.ToSharedRef(), &RawObject::DelegateTest);
        break;
        case EDelegateType::Static: //绑定静态函数
            Delegate.BindStatic(&&RawObject::DelegateStatic);
        break;
        case EDelegateType::UFunction:  //绑定UE4对象,特点是用名字(字符串)找到函数,方法需要加UFUNCTION()宏
            if(UEObject == nullptr)
            {
                UEObject = NewObject<UDelegateObject>();
            }
            Delegate.BindUFunction(UEObject, "TestDelegateUFunction");
        break;
        case EDelegateType::WeakLambda: //4.21新加的弱Lambda表达式,在执行时,会先检查 UEObject 的指针,如果指针失效了就不会执行Lambda表达式
            if(UEObject == nullptr)
            {
                UEObject = NewObject<UDelegateObject>();
            }
            Delegate.BindWeakLambda(UEObject, []{void}{
                UE_LOG(LogTemp, Warning, TEXT(_FUNCTION_));
            });
        break;
        default:
        break;
    }
}

委托调用

if(Maker == nullptr)
{
    Maker = NewObject<UDelegateMaker>();
}
Maker -> MakeDelegate(Type).ExecutelfBound();