콘텐츠로 이동

C++ 캐스팅 연산자 완전 가이드

왜 C++ 캐스팅 연산자를 써야 하는가

섹션 제목: “왜 C++ 캐스팅 연산자를 써야 하는가”

C 스타일 캐스트 (Type)expr는 여러 종류의 변환을 묵시적으로 수행해 의도를 숨깁니다. C++ 캐스팅 연산자는 의도를 명시하고 잘못된 변환을 컴파일 타임 또는 런타임에 잡아줍니다.

컴파일 타임에 검사하는 명시적 변환입니다.

// 수치 변환
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를 사용하세요.

런타임에 타입을 검사하는 안전한 다운캐스트입니다. 다형성 타입(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) {
// 타입 불일치
}

비트를 그대로 재해석하는 저수준 캐스트입니다.

// 포인터 ↔ 정수
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 위반 가능성이 높습니다. 하드웨어 레지스터 접근, 직렬화 등 꼭 필요한 경우에만 사용하세요.

constvolatile추가하거나 제거합니다.

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로 수정하면 미정의 동작입니다.

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