#define UCLASS(ClassName, ParentClass) \
public: \
static UClass* StaticClass() { \
static UClass StaticClassInstance(#ClassName, ParentClass::StaticClass()); \
return &StaticClassInstance; \
} \
virtual UClass* GetClass() const { return StaticClass(); }
위 매크로를 사용하면.
class A : public SceneComp
{
UCLASS(A, SceneComp)
public:
//기타...
}
아래처럼 코드 확장.
class A : public sceneComp
{
static UClass* StaticClass() {
static UClass StaticClassInstance(#ClassName, ParentClass::StaticClass());
return &StaticClassInstance;
}
virtual UClass* GetClass() const { return StaticClass(); }
public:
//기타...
}
StaticClass( ) 함수 호출 순서
1. A::StaticClass( ) 호출
2. 부모 클래스의 StaticClass () 호출
- A의 StaticClassInstance를 생성하기 위해 생성자 인자중 두 번째 인자는 sceneComp::StaticClass();
- A를 생성하기 전에, A의 부모 클래스인 sceneComp의 StaticClass함수가 호출되어 sceneComp 클래스의 메타데이터 객체 초기화 됨.
3. 재귀적 부모 체인 호출.
sceneComp 클래스 또한 UCLASS 매크로를 사용하여 정의되어있으므로 sceneComp 내부에도 StaticClass()함수가 존재.
이 과정은 sceneComp의 부모 클래스이 StaticClass 호출로 이어지고 결국 최상위인 UClass의 StaticClass에 도달.
UClass의 StaticClass()
class UClass {
public:
static UClass* StaticClass() {
static UClass RootClass("UClass", nullptr);
return &RootClass;
}
// 기타 멤버들...
};
최종적으로 UClass::StaticClass()는 "UClass"라는 이름의 루트 메타데이터 주소 반환.
4. A클래스의 정적 변수 초기화 완료
부모 체인에서 모든 StaticClass( ) 호출이 완료되면, A::StaticClas()의 정적 변수 StaticClassInstance가 "A"라는 이름과 sceneComp의 메타데이터를 인자로 생성됨.
5. A::StaticClass() 반환.
마지막으로, 생성된 StaticClassInstance의 주소가 반환되어 A클래스이 메타데이터로 활용.
IsA
//UObject.h
template<typename T>
bool IsA()
{
return GetClass()->IsA<T>();
}
// UClass.h
bool IsChildOf(const UClass* ParentClass) const
{
const UClass* Class = this;
while (Class)
{
if (Class == ParentClass)
{
return true;
}
Class = Class->SuperClass;
}
return false;
}
template<typename T>
bool IsA() const
{
return IsChildOf(T::StaticClass());
}
UObject 쪽의 IsA() 함수는 현재 객체의 GetClass()를 호출하여 그 객체의 UClass(메타데이터)를 얻음.
그런 다음 이 UClass 객체의 IsA<T>()를 호출.
UClass의 IsA<T>() 함수는 템플릿 인자로 받은 T 클래스의 StaticClass()를 이용해,
현재 클래스의 상속 체인 내에 T 클래스의 메타데이터가 있는지를 IsChildOf() 함수를 통해 확인.
'TIL' 카테고리의 다른 글
UE Actor 라이프사이클 (0) | 2025.03.21 |
---|---|
World Grid 렌더링 최적화: 두 가지 접근 방식 (0) | 2025.03.18 |
std::vector erase, std::remove 관련 (0) | 2025.03.18 |
FName (0) | 2025.03.18 |
Today I Learned (0) | 2025.02.24 |