C++ 캐스팅 연산자 완전 가이드
왜 C++ 캐스팅 연산자를 써야 하는가
섹션 제목: “왜 C++ 캐스팅 연산자를 써야 하는가”C 스타일 캐스트 (Type)expr는 여러 종류의 변환을 묵시적으로 수행해 의도를 숨깁니다. C++ 캐스팅 연산자는 의도를 명시하고 잘못된 변환을 컴파일 타임 또는 런타임에 잡아줍니다.
static_cast
섹션 제목: “static_cast”컴파일 타임에 검사하는 명시적 변환입니다.
// 수치 변환double d = 3.14;int i = static_cast<int>(d); // 명시적 잘림
// 관련 타입 간 변환 (업캐스트/다운캐스트)class Base { virtual void f() {} };class Derived : public Base {};
Derived* dp = new Derived();Base* bp = static_cast<Base*>(dp); // 업캐스트: 안전
Derived* dp2 = static_cast<Derived*>(bp); // 다운캐스트: bp가 실제로 Derived인지 보장 없음다운캐스트 시 실제 타입을 보장해야 한다면 dynamic_cast를 사용하세요.
dynamic_cast
섹션 제목: “dynamic_cast”런타임에 타입을 검사하는 안전한 다운캐스트입니다. 다형성 타입(virtual 함수 포함)에서만 사용 가능합니다.
class Animal { virtual ~Animal() {} };class Dog : public Animal { void bark() {} };class Cat : public Animal { void meow() {} };
Animal* a = new Dog();
// 포인터: 실패 시 nullptr 반환if (Dog* dog = dynamic_cast<Dog*>(a)) { dog->bark(); // 성공}
if (Cat* cat = dynamic_cast<Cat*>(a)) { cat->meow(); // 실행 안 됨 (nullptr)}
// 참조: 실패 시 std::bad_cast 예외try { Dog& dog = dynamic_cast<Dog&>(*a);} catch (const std::bad_cast& e) { // 타입 불일치}reinterpret_cast
섹션 제목: “reinterpret_cast”비트를 그대로 재해석하는 저수준 캐스트입니다.
// 포인터 ↔ 정수uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);void* restored = reinterpret_cast<void*>(addr);
// 관련 없는 포인터 타입 간 변환int n = 0x12345678;char* bytes = reinterpret_cast<char*>(&n);// bytes[0]은 리틀 엔디안에서 0x78
// 함수 포인터 변환using FuncPtr = void(*)();FuncPtr fp = reinterpret_cast<FuncPtr>(someAddress);reinterpret_cast는 Strict Aliasing Rule 위반 가능성이 높습니다. 하드웨어 레지스터 접근, 직렬화 등 꼭 필요한 경우에만 사용하세요.
const_cast
섹션 제목: “const_cast”const나 volatile을 추가하거나 제거합니다.
void print(char* str) { printf("%s", str); } // const 미지원 레거시 API
const char* msg = "hello";print(const_cast<char*>(msg)); // const 제거 — 수정하지 않는다는 전제
// const 멤버 함수에서 예외적 수정class Cache { mutable int count_ = 0;public: int get() const { const_cast<Cache*>(this)->count_++; // mutable 대신 (비권장) return count_; }};원래 const로 선언된 객체를 const_cast로 수정하면 미정의 동작입니다.
C 스타일 캐스트의 문제
섹션 제목: “C 스타일 캐스트의 문제”Base* b = new Base();// C 스타일: static_cast, reinterpret_cast, const_cast 중 하나를 순서대로 시도Derived* d = (Derived*)b; // 의도 불명, 오류 감지 불가
// C++ 스타일: 의도 명확Derived* d2 = static_cast<Derived*>(b); // 관련 타입 변환선택 가이드
섹션 제목: “선택 가이드”| 상황 | 사용할 캐스트 |
|---|---|
| 수치 변환, 업캐스트, 명시적 변환 | static_cast |
| 안전한 다운캐스트 (런타임 검사) | dynamic_cast |
| 포인터 ↔ 정수, 비트 재해석 | reinterpret_cast |
| const/volatile 제거 | const_cast |
- C 스타일 캐스트 대신 C++ 캐스트를 사용해 의도를 명확히 표현
- 다운캐스트는
dynamic_cast로 런타임 안전성 확보 reinterpret_cast는 Aliasing 위반 주의, 꼭 필요한 곳에만const_cast로 실제 const 객체를 수정하면 UB