// Dynamically cast an object type-safely.
template <typename To, typename From>
FORCEINLINE To* Cast(From* Src)
{
return TCastImpl<From, To>::DoCast(Src);
}
TCastImpl有多个模板实例:
// 通用模板实例
template <typename From, typename To, ECastType CastType = TGetCastType<From, To>::Value>
struct TCastImpl
{
// This is the cast flags implementation
FORCEINLINE static To* DoCast( UObject* Src )
{
return Src && Src->GetClass()->HasAnyCastFlag(TCastFlags<To>::Value) ? (To*)Src : nullptr;
}
FORCEINLINE static To* DoCastCheckedWithoutTypeCheck( UObject* Src )
{
return (To*)Src;
}
};
// object cast to object
template <typename From, typename To>
struct TCastImpl<From, To, ECastType::UObjectToUObject>
{
FORCEINLINE static To* DoCast( UObject* Src )
{
return Src && Src->IsA<To>() ? (To*)Src : nullptr;
}
FORCEINLINE static To* DoCastCheckedWithoutTypeCheck( UObject* Src )
{
return (To*)Src;
}
};
// interface to object
template <typename From, typename To>
struct TCastImpl<From, To, ECastType::InterfaceToUObject>
{
FORCEINLINE static To* DoCast( From* Src )
{
To* Result = nullptr;
if (Src)
{
UObject* Obj = Src->_getUObject();
if (Obj->IsA<To>())
{
Result = (To*)Obj;
}
}
return Result;
}
FORCEINLINE static To* DoCastCheckedWithoutTypeCheck( From* Src )
{
return Src ? (To*)Src->_getUObject() : nullptr;
}
};
// object to interface
template <typename From, typename To>
struct TCastImpl<From, To, ECastType::UObjectToInterface>
{
FORCEINLINE static To* DoCast( UObject* Src )
{
return Src ? (To*)Src->GetInterfaceAddress(To::UClassType::StaticClass()) : nullptr;
}
FORCEINLINE static To* DoCastCheckedWithoutTypeCheck( UObject* Src )
{
return Src ? (To*)Src->GetInterfaceAddress(To::UClassType::StaticClass()) : nullptr;
}
};
// interface to interface
template <typename From, typename To>
struct TCastImpl<From, To, ECastType::InterfaceToInterface>
{
FORCEINLINE static To* DoCast( From* Src )
{
return Src ? (To*)Src->_getUObject()->GetInterfaceAddress(To::UClassType::StaticClass()) : nullptr;
}
FORCEINLINE static To* DoCastCheckedWithoutTypeCheck( From* Src )
{
return Src ? (To*)Src->_getUObject()->GetInterfaceAddress(To::UClassType::StaticClass()) : nullptr;
}
};
文件Cast.h中还有其他几种模板实例, 这里只讲做常用的Object to object:
template <typename From, typename To>
struct TCastImpl<From, To, ECastType::UObjectToUObject>
{
FORCEINLINE static To* DoCast( UObject* Src )
{
return Src && Src->IsA<To>() ? (To*)Src : nullptr;
}
FORCEINLINE static To* DoCastCheckedWithoutTypeCheck( UObject* Src )
{
return (To*)Src;
}
};
在DoCast中, 会调用 UObject的IsA函数:
/** Returns true if this object is of the template type. */
template<class T>
bool IsA() const
{
return IsA(T::StaticClass());
}
/** Returns true if this object is of the specified type. */
template <typename OtherClassType>
FORCEINLINE bool IsA( OtherClassType SomeBase ) const
{
// We have a cyclic dependency between UObjectBaseUtility and UClass,
// so we use a template to allow inlining of something we haven't yet seen, because it delays compilation until the function is called.
// 'static_assert' that this thing is actually a UClass pointer or convertible to it.
const UClass* SomeBaseClass = SomeBase;
(void)SomeBaseClass;
checkfSlow(SomeBaseClass, TEXT("IsA(NULL) cannot yield meaningful results"));
const UClass* ThisClass = GetClass();
// Stop the compiler doing some unnecessary branching for nullptr checks
ASSUME(SomeBaseClass);
ASSUME(ThisClass);
return IsChildOfWorkaround(ThisClass, SomeBaseClass);
}
template <typename ClassType>
static FORCEINLINE bool IsChildOfWorkaround(const ClassType* ObjClass, const ClassType* TestCls)
{
return ObjClass->IsChildOf(TestCls);
}
会调用到Class.cpp文件中的 UStruct::IsChildOf函数, 该函数会遍历所有继承串链, 每一个都要判断和目标类型是否相等.
/**
* @return true if this object is of the specified type.
*/
#if USTRUCT_FAST_ISCHILDOF_COMPARE_WITH_OUTERWALK || USTRUCT_FAST_ISCHILDOF_IMPL == USTRUCT_ISCHILDOF_OUTERWALK
bool UStruct::IsChildOf( const UStruct* SomeBase ) const
{
if (SomeBase == nullptr)
{
return false;
}
bool bOldResult = false;
for ( const UStruct* TempStruct=this; TempStruct; TempStruct=TempStruct->GetSuperStruct() )
{
if ( TempStruct == SomeBase )
{
bOldResult = true;
break;
}
}
#if USTRUCT_FAST_ISCHILDOF_IMPL == USTRUCT_ISCHILDOF_STRUCTARRAY
const bool bNewResult = IsChildOfUsingStructArray(*SomeBase);
#endif
#if USTRUCT_FAST_ISCHILDOF_COMPARE_WITH_OUTERWALK
ensureMsgf(bOldResult == bNewResult, TEXT("New cast code failed"));
#endif
return bOldResult;
}
#endif
网友评论