static_cast
- 컴파일 타임에 수행되는 캐스트
- 업캐스팅(Upcasting) 및 (개발자가 이미 다운캐스팅이 유효함을 100% 확신할 수 있는 상황) 안전한 다운캐스팅(Downcasting)
- 업캐스팅은 명시적 캐스팅을 할 필요가 없더라도, 코드의 의도를 분명히 하기 위해 사용한다.
- 다운캐스팅은 타입 정보를 검사하지 않고 강제 변환하므로, 런타임에 안전성이 보장되지 않는다.
- 내장형 타입 간 변환
- ex)
double을 int로 캐스팅하거나, int를 char로 캐스팅하는 경우 등.
- 오버로딩된 형변환 연산자를 호출
- C 스타일 캐스팅보다 안전하고 명시적
int hp = 100;
int maxHp = 200;
float ratio = static_cast<float>(hp) / maxHp;
dynamic_cast
- 주로 다운캐스팅(Downcasting)을 안전하게 수행하기 위해 사용되는 연산자이다.
- 상속 관계에서의 안전 변환을 하는 캐스트
- 다형성을 활용한 방식 (VTable을 통해서 타입을 읽어야한다.)
- 런타임 타입 정보(RTTI, Run-Time Type Information) 활용
- 런타임 체크를 수행하므로,
static_cast에 비해 추가 비용이 발생할 수 있다.
class Player
{
public:
Player() {}
virtual ~Player() {}
};
class Archer: public Player
{
public:
Archer() {}
~Archer() {}
};
class Knight : public Player
{
public:
Knight() {}
~Knight() {}
};
int main() {
Archer* a = new Archer();
Player* p = a;
Knight* k = dynamic_cast<Knight*>(p);
if (k != nullptr)
{
}
}
const_cast
- const를 제거하거나 추가할 때 사용한다.
- 추가하는 것은 드문 경우이고, 주로
const를 제거하여 수정이 불가능했던 변수를 수정할 수 있도록 하는 경우에 사용된다.
const char* name = "Strong";
char* name2 = const_cast<char*>(name);
reinterpret_cast
- 서로 전혀 관련 없는 포인터 타입 간 변환
- 비트 패턴을 직접 해석해야 하는 상황
- ex) float의 내부 표현을 int로 보고 싶을 때, 또는 특정 구조체를 raw byte 배열로 다뤄야 할 때.
Knight* k = new Knight();
int address = reinterpret_cast<int>(k);