C의 캐스트 연산자의 문제점
C의 캐스트 연산자는 책임이 모두 개발자에게 있다. 원하는대로 바꿔 줄테니 결과가 어찌 되든 상관 없다는 식이다. 그래서 C++에서는 좀 더 안전하고 변환 목적에 맞게 골라 쓸 수 있는 4개의 새로운 캐스트 연산자를 제공한다. 이 연산자들은 C의 캐스트 연산자에 비해 규칙이 다소 엄격해 실수를 줄일 뿐만 아니라 어떤 의도의 타입 변환인지를 좀 더 분명히 표시하는 장점이 있다.
static_cast 연산자
static_cast 연산자는 지정한 타입으로 변경하는데 무조건 변경하는 것이 아니라 논리적으로 변환 가능한 타입만 변환한다.
기본형태
static_cast< type >( 대상 )
가능한 경우
실수형 -> 정수형
정수형 -> 실수형
상호 호환되는 열거형과 정수형과의 변환
double, float의 변환 등도 허용
불가능한 경우
포인터의 타입을 다른 것으로 변환하는 것 -> 컴파일 에러
( 되는 경우 : 상속 관계에 있는 클래스 포인터끼리만 변환이 허용 )
( 클래스 포인터도 up캐스팅은 안전하지만 down캐스팅은 불안전 )
dynamic_cast 연산자
dynamic_cast 연산자는 포인터끼리 또는 레퍼런스끼리 변환하는데 반드시 포인터는 포인터로 변환해야하고 레퍼런스는 레퍼런스로 변환해야 한다. 포인터를 레퍼런스로 바꾸거나 레퍼런스를 포인터로 변환하는 것은 상식적으로 필요하지도 않고 가능하지도 않다. 포인터끼리 변환할 때도 반드시 상속 계층에 속한 클래스끼리만 변환할 수 있다.
그래서 UP캐스팅은 안전하여 가능하지만 DOWN캐스팅은 자식에게만 있는 멤버를 참조할 수 있기 때문에 위험하다 dynamic_cast 연산자는 DOWN캐스팅할 때 NULL을 반환하여 위험한 변환을 허가하지 않는다.
주로 상속 관계에 있는 포인터를 캐스팅할 때 사용하고 레퍼런스에 대해서도 캐스팅할 수 있다. 단, 레퍼런스는 에러에 해당하는 NULL을 리턴할 수 없으므로 대신 bad_cast 예외를 던진다. 따라서 레퍼런스를 변환할 때는 반드시 캐스팅 코드를 try 블록에 작성하고 bad_cast 예외를 잡아서 처리해야 한다.
const_cast 연산자
이 캐스트 연산자는 포인터의 상수성만 변경하고 싶을 때 사용한다. 상수 지시 포인터를 비상수 지시 포인터로 잠시 바꾸고 잠시 바꾸고 싶을 때 const_cast 연산자를 쓴다. 변수의 상수성만 변경할 수 있고 타입을 바꿀 수는 없다. 오로지 포인터의 상수성만을 변경할 수 있다. 그래서 이 캐스트 연산자를 사용하면 다른 엉뚱한 변환을 피할 수 있어 더 안전하며 코드를 읽는 사람도 어떤 의도로 이 캐스트 연산자를 사용했는지 쉽게 파악할 수 있다.
reinterpret_cast 연산자
reinterpret_cast 연산자는 임의의 포인터 타입끼리 변환을 허용하는 상당히 위험한 캐스트 연산자이다. 심지어 정수형과 포인터간의 변환도 허용된다. 정수형값을 포인터 타입으로 바꾸어 절대 번지를 가리키도록 한다거나 할 때 이 연산자를 사용한다. 이 연산자는 포인터 타입간의 변환이나 포인터와 수치형 데이터의 변환에만 사용하며 기본 타입들끼리의 변환에는 사용할 수 없다.
정리
cast 연산자 |
변환 형태 |
static_cast |
상속 관계의 클래스 포인터 및 레퍼런스 기본타입 타입 체크 안함 |
dynamic_cast |
상속관계의 클래스 포인터 및 레퍼런스 타입체크 RTTI 기능 필요 |
const_cast |
const, volatile 등의 속성 변경 |
reinterpert_cast |
포인터끼리 포인터와 수치형간의 변환 |