c++ 형변환 연산자(static_cast, const_cast, reinterpret_cast, dynamic_cast)
double d = 3.14;
int i = (int)d;
이런 형변환은 C스타일 형변환 혹은 명시적 형변환 이라고 부른다.
암시적 형변환이 불가능하다는 뜻을 담고 있고, 형변환의 의도를 구별해내기 힘들다는 문제점이 있다.
그래서 C++에서는 4가지 형변환연산자를 제공한다.
static_cast
정적 형변환. 가장 일반적인 형태의 형변환이다.
A타입에서 B타입으로 암시적인 형변환이 가능하다면 static_cast를 사용해 형변환 할 수 있다.
기본 자료형 데이터 간 형변환과 클래스 상속관계에서의 형변환만 허용한다.
double d = 3.14;
int i = static_cast<int>(d);
const_cast
const속성이나 volatile 속성을 제거할 때 사용.
*volatile : 가끔 컴파일러가 변수를 상수로 만들어버리는 작업을 수행. volatile로 그 작업에서 제외시킨다. 멀티스레드에서 사용할 수 있음.
const int value = 100;
int i = const_cast<int>(value);
reinterpret_cast
포인터/참조 관련된 형변환. 전혀 상관없는 자료형으로의 형변환에 사용된다.
int num = 0x01020304;
char* ptr = reinterpret_cast<char*>(&num);
if(ptr[0] == '\x04')
std::cout<< "little-endian"; // 리틀엔디안. [04][03][02][01]
else
std::cout<< "big-endian"; // 빅엔디안. [01][02][03][04]
dynamic_cast
서로 상속관계에 있고 가상함수를 지니는 클래스간 형변환 할때 사용된다.
형변환과 동시에 이 형변환이 안전한지까지 검사해준다.
-> 형변환 했을 때 가리킬 수 없는 타입으로 형변환 할 경우 nullptr 반환
#include <iostream>
class Animal {
public:
virtual void move() const {
std::cout << "Animal - move" << std::endl;
}
};
class Dog : public Animal {
public:
virtual void move() const override{
std::cout << "Dog - move" << std::endl;
}
};
int main()
{
// 컴파일 OK
Animal* animal1 = new Dog();
Dog* dog1 = static_cast<Dog*>(animal1);
dog1->move();
// 컴파일은 되지만 왜 이런짓을?
Animal* animal2 = new Animal();
Dog* dog2 = static_cast<Dog*>(animal2);
dog2->move();
// 컴파일 OK
Dog* dog3 = dynamic_cast<Dog*>(animal1);
dog3->move();
// dog4는 nullptr을 가르킴
Dog* dog4 = dynamic_cast<Dog*>(animal2);
if(dog4)
dog4->move();
}
- 기본 자료형간 형변환은 static_cast
- 상속관계에서 안정적인 형변환을 원한다면 dynamic_cast
- 상속관계에서 때로는 형변환을 강제해야 하는 상황이라면 static_cast
- 포인터/참조 타입에 상관없이 무조건 형변환을 강제하고 싶다면 reinterpret_cast
- const 성향을 없애고 싶다면 const_cast