윈도우 소켓에서 reinterpret_cast라는 캐스팅을 처음 봐서 캐스팅 종류에 대해 알아보고자 포스팅했습니다.
🎯 캐스팅
캐스팅(Casting)이란 어떤 데이터의 자료형(Type)을 다른 자료형으로 변환하는 것을 의미합니다.
캐스팅의 종류로는 암시적 변환(Implicit)과 명시적 변환(Explicit) 두 가지로 나눌 수 있으며 암시적 변환은 컴파일러가 자동으로 변환해 주고 명시적 변환은 프로그래머가 직접 변환하는 것을 말합니다.
C++에서 캐스팅은 아래 네 가지 캐스팅 키워드로 할 수 있으며 버전에 따라 캐스팅 방법이 추가됐을 수 있습니다.
💡 info
Q. 왜 C 스타일의 형 변환을 사용하지 않을까?
A. C 형 변환 스타일은 강력하지만 안전하지 않습니다. 한 가지 예를 들어보면,
1 2 3 4const int number = 10; // 상수 선언 int* p = &number; // ⚠️ const int*를 int*로 받음 *p = 20; // 💀 역참조해서 변경위와 같은 상황이 발생할 수 있고, 프로그램 버그로 이어질 수 있습니다.
static_cast
💡 일반적으로 가장 많이 사용하는 캐스팅
컴파일러가 허용하는 일반적인 타입 변환을 명시적으로 수행합니다.
숫자 타입 변환
1 2 3 4double value = 3.14; int result = static_cast<int>(value); // result = 3- ⚠️ 타입 크기가 큰 곳에서 작은 곳으로 캐스팅 될 경우 데이터 손실 위험!
void*변환1 2 3 4int value = 10; void* ptr = &value; int* intPtr = static_cast<int*>(ptr);상속 관계 변환
1 2 3 4 5 6 7class Base {}; class Derived : public Base {}; Derived derived; Base* base = &derived; // Upcast Derived* ptr = static_cast<Derived*>(base); // Downcast- ⚠️ 다운 캐스팅할 때 실제 객체가
Derived인지 런타임에서 확인하지 않음!
- ⚠️ 다운 캐스팅할 때 실제 객체가
dynamic_cast
💡 런타임 타입 검사
상속 관계에서 실제 객체의 타입을 확인하면서 변환할 때 사용합니다.
일반적으로 부모 객체에 하나 이상의 virtual 함수가 있어야(RTTI1) 합니다.
- 포인터 변환
1 2 3 4 5 6 7 8 9Base* base = new Derived(); Derived* derived = dynamic_cast<Derived*>(base); if (derived) { derived->Execute(); } delete base; - 참조 변환
1 2 3 4 5 6 7 8Base& base = someObject; try { Derived& derived = dynamic_cast<Derived&>(base); } catch (const std::bad_cast&) { // 변환 실패 }
const_cast
⚠️ 사용 주의
const와 volatile 한정자를 추가하거나 제거합니다. 객체에 대한 무결성 검사를 하지 않습니다.
| |
reinterpret_cast
💀 가장 주의가 필요한 캐스팅
서로 관련 없는 타입 사이에서 포인터나 참조 등을 재해석할 때 사용합니다.
- 타입 재해석
1 2 3 4 5int value = 10; int* ptr = &value; char* charPtr = reinterpret_cast<char*>(ptr); - 포인터 → 정수형 or 정수형 → 포인터
1 2std::uintptr_t address = reinterpret_cast<std::uintptr_t>(ptr);
📝 마무리
캐스팅은 가급적이면 C++ 캐스팅 방법의 static_cast와 dynamic_cast를 사용하고 특수한 경우에는 reinterpret_cast를 사용해야 할 것 같습니다. 👍
RTTI(Run-Time Type Information 또는 Run-Time Type Identification)는 프로그램이 실행 중(Runtime)에 객체의 실제 타입(자료형)을 확인하거나 식별할 수 있도록 해주는 C++ 메커니즘입니다. ↩︎