C++의 형변환(캐스팅, Casting)에 대하여
캐스팅의 종류
1. 암시적(Implicit) 캐스팅
컴파일러가 자동으로 형 변환을 수행
합니다.
- 단, 변환이 허용되는 범위 내에서만 가능합니다.
- 프로그래머가 명시적으로 형 변환을 작성하지 않은 경우 발생합니다.
2. 명시적(Explicit) 캐스팅
- 프로그래머가 직접 형 변환 코드를 작성합니다.
- C++에서 제공하는 명시적 캐스팅:
static_cast
const_cast
dynamic_cast
(C++98 이후 도입)reinterpret_cast
C 스타일 캐스팅
1
2
double a = 1.354;
int b = (int)a;
- C 스타일 캐스팅은 C++의 네 가지 캐스팅 중 하나를 수행합니다.
- 하지만 어떤 캐스팅이 수행될지 명확하지 않습니다.
- 컴파일러가 명백한 실수를 잡아내지 못할 가능성이 있습니다.
- 이러한 문제를 해결하기 위해 C++ 스타일 캐스팅이 도입되었습니다.
- 실행 성능에는 C/C++ 모두 차이가 없습니다. (기계어 수준에서는 동일)
C++ 캐스팅의 종류
1. static_cast
용도
- 두 숫자 형 간 변환:
- 값을 유지하나, 반올림 오차가 발생할 수 있습니다.
- 이진수 표기가 달라질 수 있습니다.
- (예:
float
→int
)
- (예:
- 포인터 간 변환:
- 변수형 체크 후 베이스 클래스를 파생 클래스로 변환
- 형식적 문법만 검사합니다.
- 변환하려는 형(Type)과 변환 하려는 포인터 변수의 형(Type) 간의 상속 관계만 검사한다.
- 변환 하려는 포인터가 실제로 가리키는 객체에 대한 형에 대해서는 검사하지 않습니다.
주의점
- 런타임 타입 검사를 수행하지 않으며, 변환된 포인터가 실제로 올바른 객체를 가리키는지 확인하지 않습니다.
- 잘못된 변환으로 인해 정의되지 않은 동작(예: 메모리 접근 오류, 프로그램 크래시)이 발생할 수 있습니다.
2. reinterpret_cast
용도
- 포인터와 비포인터 간 변환:
- 예:
Cat*
↔unsigned int
.
- 예:
- 연관이 없는 두 포인터 간 변환:
- 예:
Cat*
↔House*
. - 예:
char*
↔int*
- 예:
- 이진수 표기를 그대로 유지하며, 단순히 형식을 바꾸는 작업입니다.
주의점
- 변환 후 데이터가 실제로 의미를 가지는지는 프로그래머가 보장해야 합니다.
- 잘못된 사용 시, 심각한 버그와 프로그램 크래시가 발생할 수 있습니다.
3. const_cast
용도
const
또는volatile
속성을 제거합니다.- 예:
const int*
→int*
.
- 예:
- 주로 포인터 타입에 사용하는 것이 권장됩니다.
주의점
const_cast
로 형을 변경할 수는 없습니다.값 타입에는 권장되지 않습니다. 값이 복사되기 때문에
const
제거가 필요하지 않습니다.일반적으로
const_cast
는 써드파티 라이브러리가 const를 잘못 사용하는 경우에만 사용됩니다.const_cast
사용이 필요하다면 설계 자체를 다시 검토해보아야 합니다.
4. dynamic_cast
용도
- 런타임에 타입 검사를 수행하며, RTTI(Run-Time Type Information)를 사용합니다.
포인터 또는 참조 타입 간 캐스팅에만 사용 가능합니다.
- 변환이 올바르지 않은 경우:
- 포인터 변환:
nullptr
반환. - 참조 변환:
std::bad_cast
예외 발생.
- 포인터 변환:
주의점
- RTTI가 활성화되어야 합니다.
- RTTI는 런타임 성능에 영향을 미칠 수 있어 일반적으로는 비활성화 합니다.
- RTTI가 비활성화된 경우,
dynamic_cast
는static_cast
처럼 동작합니다.
- 가상 함수가 정의된 클래스에서만 동작합니다.
- 클래스가 가상 함수 테이블(vtable)을 포함해야 하며, 이를 위해 가상 소멸자나 기타 가상 함수를 명시해야 합니다.
캐스팅 가이드라인
- 기본적으로
staitc_cast
를 쓸 것reinterpret_cast<Cat*>
대신static_cast<Cat*>
- 만약
Cat
이Animal
이 아니라면 컴파일러가 에러를 뱉음
- 만약
- 필요한 경우
reinterpret_cast
를 쓸것- 포인터와 비포인터 사이의 변환
- 이걸 정말 해야 할 때가 있음 (ex. 포인터 주소의 저장)
- 서로 연관이 없는 포인터 사이의 변환은 그 데이터형이 맞다고 정말 확신할 때만 할 것
- 포인터와 비포인터 사이의 변환
- 내가 변경 권한이 없는 외부 라이브러리를 호출할 때만
const_cast
를 쓸 것
This post is licensed under CC BY 4.0 by the author.