美文网首页
UE4 Cast 详解

UE4 Cast 详解

作者: 我真的不知道该起什么名字了 | 来源:发表于2019-06-14 11:11 被阅读0次
// 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

相关文章

  • UE4 Cast 详解

    TCastImpl有多个模板实例: 文件Cast.h中还有其他几种模板实例, 这里只讲做常用的Object to ...

  • C++类型转换

    static_cast dynamic_cast const_cast reinterpret_cast 1. s...

  • sql常用函数

    1.CAST 语法 类型强转:CAST ( AS [ length ]);cast( 列...

  • 霸刀宏

    鞘刀段: /cast坚壁清野·二式 /cast坚壁清野 /cast[buff:含风]醉斩白蛇 /cast刀啸风吟 ...

  • 类型转换

    类型转换: static_cast static_cast:static_cast < type-id > ( e...

  • 使用c++风格显式类型转换

    四种显式类型转换 static_cast dynamic_cast const_cast reinterpret_...

  • C++11新特性(3)

    1.类型强制转换 static_cast,interpret_cast,const_cast和dynamic_ca...

  • C/C++ static_cast/dynamic_cast/c

    Qt之数据类型转换原文连接static_cast dynamic_cast const_cast reinterp...

  • HiveSql

    -- 类型转换:cast SELECT CAST('00321' AS BIGINT) FROM table; -...

  • UE4 毛发渲染参考文章

    《UE4 头发制作流程》《ue4 4.24测试功能groom头发》《Digital Human UE4 TEST ...

网友评论

      本文标题:UE4 Cast 详解

      本文链接:https://www.haomeiwen.com/subject/hpdufctx.html