普通單播的定義
#define DECLARE_DELEGATE( DelegateName ) FUNC_DECLARE_DELEGATE( DelegateName, void )
#define FUNC_DECLARE_DELEGATE( DelegateName, ... ) \
typedef TBaseDelegate<__VA_ARGS__> DelegateName;
class TBaseDelegate<void, ParamTypes...>: public TBaseDelegate<TTypeWrapper<void>, ParamTypes...>
{
// ···
}
實際上是一個TBaseDelegate子類, 看父類TBaseDelegate<TTypeWrapper, ParamTypes…>的定義
template <typename WrappedRetValType, typename... ParamTypes>
class TBaseDelegate : public FDelegateBase
{
public:
/** 定義了返回的類型. */
typedef typename TUnwrapType<WrappedRetValType>::Type RetValType;
// 定義一個帶有返回類型和參數的函數類型
typedef RetValType TFuncType(ParamTypes...);
/** 與此委託類兼容的委託實例類型的共享接口的類型定義. */
typedef IBaseDelegateInstance<TFuncType> TDelegateInstanceInterface;
FORCEINLINE TDelegateInstanceInterface* GetDelegateInstanceProtected() const
{
return (TDelegateInstanceInterface*)FDelegateBase::GetDelegateInstanceProtected();
}
}
內部定義了一個與此委託類兼容的委託實例類型IBaseDelegateInstance,而IBaseDelegateInstance繼承自IBaseDelegateInstanceCommon
struct IBaseDelegateInstanceCommon<RetType(ArgTypes...)> : public IDelegateInstance
{
virtual void CreateCopy(FDelegateBase& Base) = 0;
virtual RetType Execute(ArgTypes...) const = 0;
};
IBaseDelegateInstanceCommon的模板參數RetType和ArgTyes和TBaseDelegate裏面的模板參數對應。
之後要介紹的綁定C++原生函數TBaseRawMethodDelegateInstance,綁定UObject對象成員函數TBaseUObjectMethodDelegateInstance,綁定UFunction的TBaseUFunctionDelegateInstance和綁定Lambada的TBaseFunctorDelegateInstance,都繼承自IBaseDelegateInstance。
然後講一講FDelegateBase,它是單播代理類的祖先類
class FDelegateBase
{
public:
FDelegateBase& operator=(FDelegateBase&& Other)
{
Unbind();
DelegateAllocator.MoveToEmpty(Other.DelegateAllocator);
DelegateSize = Other.DelegateSize;
Other.DelegateSize = 0;
return *this;
}
FORCEINLINE IDelegateInstance* GetDelegateInstanceProtected( ) const
{
return DelegateSize ? (IDelegateInstance*)DelegateAllocator.GetAllocation() : nullptr;
}
private:
FDelegateAllocatorType::ForElementType<FAlignedInlineDelegateType> DelegateAllocator;
int32 DelegateSize;
};
DelegateAllocator存儲一個IDelegateInstance對象, 通過它來實現代理,獲取代理的方式就是上面代碼裏的GetDelegateInstanceProtected(),這個方法會在TBaseDelegate裏調用。
DelegateAllocator實際上是一個ForElementType類型, 繼承自ForAnyElementType,MoveToEmpty方法,以級現在的GetAllocation方法,都是定義在ForAnyElementType中的
template<typename ElementType>
class ForElementType : public ForAnyElementType
{
public:
FORCEINLINE ElementType* GetAllocation() const
{
// 調用基類的GetAllocation()方法
return (ElementType*)ForAnyElementType::GetAllocation();
}
};
class CORE_API ForAnyElementType
{
public:
FORCEINLINE void MoveToEmpty(ForAnyElementType& Other)
{
checkSlow(this != &Other);
if (Data)
{
FMemory::Free(Data);
}
Data = Other.Data;
Other.Data = nullptr;
}
FORCEINLINE FScriptContainerElement* GetAllocation() const
{
return Data;
}
private:
FScriptContainerElement* Data;
};
然後說說具體的一些綁定過程
C++原生函數的綁定
template <typename UserClass, typename... VarTypes>
FUNCTION_CHECK_RETURN_START
inline static TBaseDelegate<RetValType, ParamTypes...> CreateRaw(UserClass* InUserObject, typename TMemFunPtrType<false, UserClass, RetValType (ParamTypes..., VarTypes...)>::Type InFunc, VarTypes... Vars)
FUNCTION_CHECK_RETURN_END
{
TBaseDelegate<RetValType, ParamTypes...> Result;
TBaseRawMethodDelegateInstance<false, UserClass, TFuncType, VarTypes...>::Create(Result, InUserObject, InFunc, Vars...);
return Result;
}
上面說了,TBaseRawMethodDelegateInstance是IBaseDelegateInstance的子類,
template <bool bConst, class UserClass, typename WrappedRetValType, typename... ParamTypes, typename... VarTypes>
class TBaseRawMethodDelegateInstance<bConst, UserClass, WrappedRetValType (ParamTypes...), VarTypes...> : public IBaseDelegateInstance<typename TUnwrapType<WrappedRetValType>::Type (ParamTypes...)>
{
public:
typedef typename TUnwrapType<WrappedRetValType>::Type RetValType;
private:
typedef IBaseDelegateInstance<RetValType (ParamTypes...)> Super;
typedef TBaseRawMethodDelegateInstance<bConst, UserClass, RetValType (ParamTypes...), VarTypes...> UnwrappedThisType;
public:
typedef typename TMemFunPtrType<bConst, UserClass, RetValType (ParamTypes..., VarTypes...)>::Type FMethodPtr;
FORCEINLINE static void Create(FDelegateBase& Base, UserClass* InUserObject, FMethodPtr InFunc, VarTypes... Vars)
{
new (Base) UnwrappedThisType(InUserObject, InFunc, Vars...);
}
virtual RetValType Execute(ParamTypes... Params) const override final
{
typedef typename TRemoveConst<UserClass>::Type MutableUserClass;
auto MutableUserObject = const_cast<MutableUserClass*>(UserObject);
checkSlow(MethodPtr != nullptr);
return Payload.ApplyAfter(TMemberFunctionCaller<MutableUserClass, FMethodPtr>(MutableUserObject, MethodPtr), Params...);
}
};
類裏面定義了返回類型別名RetValType,定義了函數指針別名FMethodPtr,這裏用到了TMemFunPtrType模板類,來看看定義
template <typename Class, typename RetType, typename... ArgTypes>
struct TMemFunPtrType<false, Class, RetType(ArgTypes...)>
{
typedef RetType (Class::* Type)(ArgTypes...);
};
它的作用就是定義一個類成員函數指針,也指明瞭返回值類型和參數類型。
然後,在Create方法裏, 在Base對象上執行TBaseRawMethodDelegateInstance的構造
FORCEINLINE static void Create(FDelegateBase& Base, UserClass* InUserObject, FMethodPtr InFunc, VarTypes... Vars)
{
new (Base) UnwrappedThisType(InUserObject, InFunc, Vars...);
}
Create方法是在TBaseDelegate裏調用的
template <typename UserClass, typename... VarTypes>
inline void BindRaw(UserClass* InUserObject, typename TMemFunPtrType<false, UserClass, RetValType (ParamTypes..., VarTypes...)>::Type InFunc, VarTypes... Vars)
{
*this = CreateRaw(InUserObject, InFunc, Vars...);
}
最後是執行過程Execute
Payload.ApplyAfter(TMemberFunctionCaller<MutableUserClass, FMethodPtr>(MutableUserObject, MethodPtr), Params...);
Payload是一個TTuple,可以看到,由於是ApplyAfter,因此綁定的函數在執行Execute的時候,先傳入我們在Execute的時候傳入的參數,再傳入Payload存儲的參數,兩者的參數組成實參列表,一定要和綁定的函數的參數列表一致。 Payload存儲的參數值,是在綁定的時候,位於綁定函數之後的參數包裏的Vars。
TBaseRawMethodDelegateInstance<false, UserClass, TFuncType, VarTypes...>::Create(Result, InUserObject, InFunc, Vars...);
有關TTuple的,可以查看TTuple的源碼分析
它裏面用到了一個TMemberFunctionCaller,它用於執行指定類對象的成員函數,並且講函數參數包進行轉發
template <typename... ArgTypes>
auto operator()(ArgTypes&&... Args) -> decltype((Obj->*MemFunPtr)(Forward<ArgTypes>(Args)...))
{
return (Obj->*MemFunPtr)(Forward<ArgTypes>(Args)...);
}
UE4重寫了Forward函數,它用來講參數轉發給另一個函數而不改變參數原有的左右值。Forward(Args)…進行包擴展,會將參數包裏每一個參數都進行一次Forward轉發。
UObject的綁定
UObject綁定和原生C++成員函數綁定類似, 分了const和非const函數的版本
TBaseUObjectMethodDelegateInstance也是一個IBaseDelegateInstance子類.
UFunction綁定
template <typename UObjectTemplate, typename... VarTypes>
FUNCTION_CHECK_RETURN_START
inline static TBaseDelegate<RetValType, ParamTypes...> CreateUFunction(UObjectTemplate* InUserObject, const FName& InFunctionName, VarTypes... Vars)
FUNCTION_CHECK_RETURN_END
{
TBaseDelegate<RetValType, ParamTypes...> Result;
TBaseUFunctionDelegateInstance<UObjectTemplate, TFuncType, VarTypes...>::Create(Result, InUserObject, InFunctionName, Vars...);
return Result;
}
TBaseUFunctionDelegateInstance和之前的兩個略有區別, CachedFunction的查找通過反射去查找
template <class UserClass, typename WrappedRetValType, typename... ParamTypes, typename... VarTypes>
class TBaseUFunctionDelegateInstance<UserClass, WrappedRetValType (ParamTypes...), VarTypes...> : public IBaseDelegateInstance<typename TUnwrapType<WrappedRetValType>::Type (ParamTypes...)>
{
public:
TBaseUFunctionDelegateInstance(UserClass* InUserObject, const FName& InFunctionName, VarTypes... Vars)
: FunctionName (InFunctionName)
, UserObjectPtr(InUserObject)
, Payload (Vars...)
, Handle (FDelegateHandle::GenerateNewHandle)
{
check(InFunctionName != NAME_None);
if (InUserObject != nullptr)
{
CachedFunction = UserObjectPtr->FindFunctionChecked(InFunctionName);
}
}
public:
UFunction* CachedFunction;
FName FunctionName;
TWeakObjectPtr<UserClass> UserObjectPtr;
TTuple<VarTypes...> Payload;
FDelegateHandle Handle;
};
在Execute的時候和上述的兩種方式不同
virtual RetValType Execute(ParamTypes... Params) const override final
{
typedef TPayload<RetValType (ParamTypes..., VarTypes...)> FParmsWithPayload;
checkSlow(IsSafeToExecute());
TPlacementNewer<FParmsWithPayload> PayloadAndParams;
Payload.ApplyAfter(PayloadAndParams, Params...);
UserObjectPtr->ProcessEvent(CachedFunction, &PayloadAndParams);
return PayloadAndParams->GetResult();
}
FParmsWithPayload構造了一個返回值爲RetValType,參數類型爲ParamTypes, 參數值爲VarTypes的Tuple. 然後調用Tuple的ApplyAfter方法。
然後在TTuple的ApplyAfter裏,會調用PayloadAndParams(),而PayloadAndParams是一個TPlacementNewer對象,它重載了函數調用符
template <typename T>
struct TPlacementNewer
{
template <typename... ArgTypes>
T* operator()(ArgTypes&&... Args)
{
check(!bConstructed);
T* Result = new (&Bytes) T(Forward<ArgTypes>(Args)...);
bConstructed = true;
return Result;
}
T* operator->()
{
check(bConstructed);
return (T*)&Bytes;
}
private:
TTypeCompatibleBytes<T> Bytes;
bool bConstructed;
};
然後執行對象的ProcessEvent, 最後調用GetResult方法。
Lambda綁定
template <typename WrappedRetValType, typename... ParamTypes, typename FunctorType, typename... VarTypes>
class TBaseFunctorDelegateInstance<WrappedRetValType(ParamTypes...), FunctorType, VarTypes...> : public IBaseDelegateInstance<typename TUnwrapType<WrappedRetValType>::Type(ParamTypes...)>
{
public:
typedef typename TUnwrapType<WrappedRetValType>::Type RetValType;
private:
typedef IBaseDelegateInstance<typename TUnwrapType<WrappedRetValType>::Type(ParamTypes...)> Super;
typedef TBaseFunctorDelegateInstance<RetValType(ParamTypes...), FunctorType, VarTypes...> UnwrappedThisType;
public:
FORCEINLINE static void Create(FDelegateBase& Base, const FunctorType& InFunctor, VarTypes... Vars)
{
new (Base) UnwrappedThisType(InFunctor, Vars...);
}
virtual RetValType Execute(ParamTypes... Params) const override final
{
return Payload.ApplyAfter(Functor, Params...);
}
private:
mutable typename TRemoveConst<FunctorType>::Type Functor;
TTuple<VarTypes...> Payload;
FDelegateHandle Handle;
};
Lambda是一個仿函數對象,TBaseFunctorDelegateInstance類用一個FDelegateHandle來記錄代理唯一ID, 類型爲uint64
最後, Execute的時候,ApplyAfter直接調用Functor,並傳入參數Params…
virtual RetValType Execute(ParamTypes... Params) const override final
{
return Payload.ApplyAfter(Functor, Params...);
}