C++ 캐스팅은 https://wkals1213.tistory.com/77
C++ Cast
암시적 캐스팅과 명시적 캐스팅이 있다. 암시적 캐스팅은 컴파일러가 자동으로 컴파일을 해줄때입니다. 명시적캐스팅은 프로그래머가 코드를 직접 작성하여 캐스팅을 해줄때입니다. 캐스팅은
wkals1213.tistory.com
.
Unreal에도 형변환하기위한 Cast 함수는 업캐스트 및 다운캐스트를 수행하는 방법을 제공하는
리플렉션 시스템이다
template <typename To, typename From>
FORCEINLINE To* Cast(From* Src)
{
return TCastImpl<From, To>::DoCast(Src);
}
TCastImpl 즉 내부에 작동되는 함수는 타입에 맞게 템플릿으로 구성이 되있는데.
(타입은 UObjectToUObject, InterfaceToUObject, UObjectToInterface, InterfaceToInterface)
DoCast
변환할수있는지 IsA함수를 통해 확인을 거친 후 static_cast를 수행하게됩니다.
template <typename From, typename To>
struct TCastImpl<From, To, ECastType::InterfaceToUObject>
{
FORCEINLINE static To* DoCast( From* Src )
{
if (Src)
{
UObject* Obj = Src->_getUObject();
if (Obj && Obj->IsA<To>())
{
return (To*)Obj;
}
}
return nullptr;
}
FORCEINLINE static To* DoCastCheckedWithoutTypeCheck( From* Src )
{
return Src ? (To*)Src->_getUObject() : nullptr;
}
};
IsA<>()는 다음과 같이 호출이 된다.
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
UE_ASSUME(SomeBaseClass);
UE_ASSUME(ThisClass);
return IsChildOfWorkaround(ThisClass, SomeBaseClass);
}
/** Returns true if this object is of the template type. */
template<class T>
bool IsA() const
{
return IsA(T::StaticClass());
}
IsChildOfWorkaround를 타고 들어가면 IsChildOf라는 함수가 나온다.
IsChildOf는 대상 유형과 같은지 여부를 확인하는 함수인듯하다.
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;
}
inline bool IsChildOf(const FFieldClass* InClass) const
{
return !!(CastFlags & InClass->GetId());
}
하지만 이건 Object만 비교했기 때문에 더 깊게는 안들어가겠습니다.
정리하자면 다음과 같습니다.
Cast<T>는 C++의 dynamic_cast<T>를 사용하지않지만 비슷하게 동작합니다.
왜냐하면 UE4는 RTTI를 무효화하고, 자체 리플렉션을 구현해서 Cast<T>를 제공하고있습니다.
DoCast함수를 를 사용하여 변환을 수행하게 되는데
UObject는 IsA함수를 사용하여 변환할수있는지 확인 후 static_cast를 수행
Interface 변환은 GetInterfaceAddress로부터 확인해서 캐스팅을 수행하게 됩니다.
만약 안전하지 않다고 판단될 경우 nullptr를 반환하게됩니다.
https://usagi.hatenablog.jp/entry/2017/12/01/ac_ue4_2
'공부 > Unreal5' 카테고리의 다른 글
Unreal 발사체 사용시 충돌체 무시방법들 (0) | 2022.07.04 |
---|---|
Unreal MatchState 상태 추가하는방법 (Custom MatchState) (0) | 2022.07.03 |
Unreal GameModeBase와 GameMode (0) | 2022.07.02 |
Unreal 서버에서 시간가져오기 Syncing Time (0) | 2022.07.02 |
총알 충돌체 처리 과정 (0) | 2022.07.01 |