캐스팅의 종류
C++에서는 크게 4가지 방식의 캐스팅이 있어
(1) static_cast
✔️ 기본적인 캐스팅 (안전한 변환)
✔️ 상속 관계에서 업캐스팅(Upcasting)에 사용
✔️ 컴파일 타임에 검사됨
cpp
복사
편집
class Animal {};
class Dog : public Animal {};
Dog myDog;
Animal* animalPtr = static_cast<Animal*>(&myDog); // Dog → Animal (업캐스팅, 안전)
🔹 Dog(자식 클래스) → Animal(부모 클래스)로 변환할 때 사용.
🔹 업캐스팅은 안전하므로 static_cast를 써도 문제가 없어.
(2) dynamic_cast
✔️ 런타임 타입 변환 (다운캐스팅에서 사용)
✔️ 형변환이 가능한지 검사 후 실패하면 nullptr 반환
✔️ 반드시 virtual 함수가 있는 클래스에서만 사용 가능
cpp
복사
편집
class Animal { public: virtual ~Animal() {} };
class Dog : public Animal {};
Animal* animal = new Dog();
Dog* dogPtr = dynamic_cast<Dog*>(animal);
if (dogPtr) {
std::cout << "변환 성공!" << std::endl;
} else {
std::cout << "변환 실패!" << std::endl;
}
🔹 Animal*을 Dog*로 변환 (다운캐스팅)
🔹 만약 animal이 실제로 Dog 객체라면 변환 성공!
🔹 animal이 Cat 객체라면 변환 실패하고 nullptr 반환
언리얼 엔진에서는?
블루프린트의 "Cast To" 노드가 dynamic_cast와 같은 역할을 해!
부모 클래스를 자식 클래스로 변환하려면 Cast To 노드를 사용해야 해.
변환 실패 시 nullptr이 반환되므로 체크가 필요해!
(3) reinterpret_cast
✔️ 메모리 주소를 강제로 변환 (위험함)
✔️ 일반적으로 사용하지 않는 게 좋음
✔️ 정말 특수한 경우(예: 네트워크, 하드웨어 메모리 조작)에 사용
cpp
복사
편집
int a = 65;
char* p = reinterpret_cast<char*>(&a);
std::cout << *p << std::endl; // 'A' (ASCII 코드 65)
🔹 숫자를 문자로 강제로 변환하는 위험한 캐스팅.
🔹 언리얼 엔진에서는 거의 사용할 일이 없어!
(4) const_cast
✔️ const 속성을 제거할 때 사용
✔️ 정말 필요한 경우가 아니라면 사용하지 않는 게 좋음
cpp
복사
편집
void PrintData(const int* num) {
int* modifiableNum = const_cast<int*>(num);
*modifiableNum = 100; // 원래는 const라서 수정 불가능하지만, 강제로 변경!
}
🔹 원래 const int*라 수정 불가능한 값을 강제로 바꿀 수 있음.
🔹 하지만 이렇게 하면 예상치 못한 버그가 생길 수 있음.
3. 정리 (언리얼 블루프린트와 비교)
💡 C++ 캐스팅과 언리얼 블루프린트 캐스트 노드 비교
C++ 캐스팅 블루프린트(BP)에서 대응되는 것 설명
static_cast 자동 형변환 (예: 부모 클래스에 자식 대입) 컴파일 타임 변환
dynamic_cast "Cast To" 노드 런타임 변환, 실패 시 nullptr
reinterpret_cast 없음 (위험해서 사용 X) 메모리 주소 강제 변환
const_cast 없음 (BP에서 const 개념이 약함) const 속성 제거
4. 초보자가 꼭 알아야 할 점!
1️⃣ 업캐스팅(자식 → 부모)은 자동 변환 가능
static_cast 사용 가능
블루프린트에서는 그냥 부모 타입에 대입 가능
2️⃣ 다운캐스팅(부모 → 자식)은 dynamic_cast(BP의 Cast To) 사용
변환이 실패할 수도 있으니 체크 필수!
3️⃣ 언리얼 블루프린트에서 "Cast To" 노드는 dynamic_cast와 유사
부모 클래스를 자식 클래스로 변환할 때 사용
변환 실패하면 nullptr이 반환되므로 체크해야 함
그렇다면~
1. 왜 다운캐스팅은 체크가 필요할까?
다운캐스팅(부모 → 자식 변환)은 무조건 성공하는 게 아니야!
부모 클래스 포인터가 실제로 해당 자식 클래스의 객체를 가리키고 있는지 확인해야 해.
만약 부모 클래스가 다른 자식 클래스를 가리키고 있다면, 다운캐스팅이 실패할 수 있어.
예를 들어:
cpp
복사
편집
class Animal { public: virtual ~Animal() {} };
class Dog : public Animal {};
class Cat : public Animal {};
Animal* animal1 = new Dog();
Animal* animal2 = new Cat();
Dog* dog1 = dynamic_cast<Dog*>(animal1); // ✅ 변환 성공 (animal1은 실제로 Dog)
Dog* dog2 = dynamic_cast<Dog*>(animal2); // ❌ 변환 실패 (animal2는 Cat이라 Dog로 변환 불가)
if (dog1) { std::cout << "dog1 변환 성공!" << std::endl; }
if (!dog2) { std::cout << "dog2 변환 실패!" << std::endl; }
🔹 animal1은 Dog 객체라 Dog*로 변환 성공
🔹 animal2는 Cat 객체라 Dog*로 변환 실패 (nullptr 반환)
2. 언리얼 블루프린트에서 Valid 체크는?
언리얼 블루프린트에서 "Cast To" 노드를 사용할 때도 변환 실패 가능성이 있어.
그래서 꼭 "Cast Failed" 핀을 체크해야 해!
✅ 올바른 사용 예제
Cast To 노드의 "Cast Failed"를 체크
성공 시에만 다음 로직 실행
🔹 만약 부모 클래스를 자식 클래스로 변환할 수 없다면, "Cast Failed" 실행됨.
🔹 블루프린트에서는 보통 "Is Valid" 노드로 체크해서 nullptr 처리도 가능해!
3. C++에서 Valid 체크하는 방법
언리얼 C++에서도 블루프린트처럼 유효성 체크(Valid Check) 를 해야 해!
cpp
복사
편집
AAnimal* Animal = GetSomeAnimal(); // 부모 클래스 포인터
ADog* Dog = Cast<ADog>(Animal); // 다운캐스팅 시도
if (Dog) // ✅ 변환 성공 시 실행
{
UE_LOG(LogTemp, Warning, TEXT("변환 성공!"));
}
else // ❌ 변환 실패 시 실행
{
UE_LOG(LogTemp, Warning, TEXT("변환 실패!"));
}
🔹 언리얼 C++에서는 Cast<Type>(Pointer)를 사용하면 언리얼 엔진 내부에서 dynamic_cast처럼 변환을 시도해!
🔹 nullptr 체크(if (Dog))를 통해 변환이 실패했는지 확인 가능!
🚀 결론: 다운캐스팅할 때는 반드시 Valid 체크를 해야 한다!
✅ C++에서는 if (ptr)로 nullptr인지 체크!
✅ 언리얼 블루프린트에서는 "Cast To" 노드의 "Cast Failed" 체크!
✅ 언리얼 C++에서는 Cast<Type>(Pointer) 후 nullptr 체크!
이걸 잘 활용하면 "Cast 실패로 인한 크래시" 같은 걸 방지할 수 있어! 😎