오늘은 C++의 RTTI와 4대 캐스팅 연산자에 대해 공부했다. 개념 자체는 알고 있었지만, 모의 면접을 통해 dynamic_cast가 동작하기 위한 정확한 조건을 내가 잘못 알고 있었다는 것을 깨달았다. 🤯 단순히 '가상 함수가 필요하다'를 넘어, 왜 그것이 '다형적(polymorphic) 클래스'라는 조건으로 이어지는지 명확히 이해하게 되었다. 런타임에 타입을 확인하는 것이 어떤 의미인지, 그리고 왜 C++이 다양한 캐스팅 연산자를 제공하는지 그 의도를 파악할 수 있었던 시간이었다.
dynamic_cast, typeid 연산자의 용도 이해하기static_cast, dynamic_cast, const_cast, reinterpret_cast의 차이점 설명하기dynamic_cast가 성공하기 위한 필수 조건 정확히 알기RTTI는 이름 그대로 '런타임 타입 정보'를 의미한다. 프로그램이 실행되는 도중에 객체의 실제 타입을 확인할 수 있게 해주는 C++의 기능이다.
dynamic_cast: 런타임에 안전하게 다운캐스팅을 시도한다. 기반 클래스 포인터가 실제로 가리키는 객체가 다운캐스팅하려는 파생 클래스 타입이 맞는지 확인한다.nullptr (포인터의 경우) 또는 bad_cast 예외 (참조의 경우)를 발생시킨다.typeid: 객체의 정확한 타입 정보를 담고 있는 type_info 객체를 반환한다. 주로 두 객체의 타입이 완전히 같은지 비교할 때 사용한다.이 기능들이 작동하려면, 컴파일러가 타입 정보를 vtable 같은 곳에 저장해둬야 한다. 그래서 RTTI는 하나 이상의 가상 함수를 가진 클래스(즉, 다형적 클래스)에서만 제대로 동작한다.
C-스타일 캐스팅 (type)value는 너무 강력하고 의도가 불분명해서, C++에서는 용도에 따라 4가지 캐스팅 연산자를 제공한다.
static_cast: 컴파일 타임에 타입을 변환한다. 논리적으로 변환 가능한 경우에 사용하며(예: int를 float으로, 파생 클래스 포인터를 기반 클래스 포인터로), 런타임 타입 체크는 하지 않는다.dynamic_cast: 위에서 설명한 RTTI를 이용한 런타임 타입 체크 캐스팅. 안전한 다운캐스팅에 사용된다.const_cast: 객체의 const나 volatile 속성을 제거할 때만 사용한다. 타입 자체를 바꾸지는 않는다.reinterpret_cast: 가장 위험한 캐스팅. 포인터나 정수형 변수 간의 비트 수준 재해석 변환을 수행한다. 관련 없는 타입 간의 변환이라 매우 조심해서 써야 한다. ⚠️dynamic_cast는 추상 클래스에만 사용할 수 있다고 생각했다.
dynamic_cast를 쓰려면 기반 클래스가 반드시 추상 클래스여야 한다.dynamic_cast는 사용 가능하다.기반 클래스 포인터가 기반 클래스 객체를 가리킬 때, dynamic_cast가 실패하는 이유를 조건 부족 탓으로만 돌렸다.
Base* p = new Base(); 일 때 dynamic_cast<Derived*>(p)가 실패하는 이유는 Base 클래스에 가상 함수가 없기 때문이다.Derived가 아니기 때문이다. dynamic_cast는 "이 포인터가 실제로 Derived 타입의 객체를 가리키고 있니?"라고 런타임에 묻는 것과 같다. Base 객체는 Derived 객체가 아니므로, 다형성 조건이 갖춰져도 캐스팅은 당연히 실패하고 nullptr를 반환한다.| 개념 | 설명 | 비고 |
|---|---|---|
| RTTI | 런타임에 객체의 실제 타입을 확인할 수 있는 기능. | dynamic_cast, typeid가 핵심 연산자. |
dynamic_cast | 런타임 타입 체크를 통해 안전하게 다운캐스팅한다. | 다형적 클래스에만 사용 가능. (가상 함수 필수) |
static_cast | 컴파일 타임에 논리적으로 관련된 타입 간 변환을 수행한다. | 런타임 비용이 없지만, 잘못된 다운캐스팅은 위험. |
const_cast | 객체의 const 또는 volatile 한정자를 제거한다. | 타입 자체를 바꾸는 것이 아님. |
reinterpret_cast | 관련 없는 타입 간의 비트 수준 재해석 변환을 수행한다. | 매우 위험하며, 거의 사용하지 않음. 💣 |