C에서는 데이터형 변환이 너무 느슨합니다.
이러한 느슨함을 해결하기 위해 Stroustrup(C++ 개발자)는 일반적인 데이터형 변환을 허용하는 것을 공고히 하고 데이터형 변환 과정을 더욱 엄격하게 규정하는 4개의 데이터형 변환 연산자를 추가하였습니다.
-
dynamic_cast
-
const_cast
-
static_cast
-
reinterpret_cast
dynamic_cast
dynamic_cast를 쓸려면 프로젝트에서 RTTI옵션을 활성화해야 합니다.
#include <iostream>
class Animal
{
public:
virtual void Move() {
std::cout << "(움직인다.)" << std::endl;
}
};
class Dog : public Animal
{
public:
void Move() {
std::cout << "멍멍멍멍!(움직인다.)" << std::endl;
}
void Say() {
std::cout << "멍멍!!" << std::endl;
}
};
int main(void) {
Dog* dog = new Dog();
Animal* a = dynamic_cast<Animal*>(dog);
}
animal 클래스가 dog형의 기초 클래스인 경우에만 변환을 합니다. 그렇지 않은 경우 널포인터를 대입합니다.
이 연산자의 목적은 어떤 클래스 계층 내에서 업캐스트를 허용하고 다른 데이터형 변환은 허용하지 않는 것입니다.
const_cast
const_cast 연산자는 어떤 값을 const나 volatile로 또는 그 반대로 변경하는 것이 유일한 목적인 데이터형 변환을 위한 것입니다.
문법은 dynamic_cast랑 동일합니다.
#include <iostream>
int main(void) {
int a = 100;
const int * ptr = &a;
*ptr = 200; //에러 발생!!
int * ptr2 = const_cast<int *>(ptr);
*ptr2 = 1000;
std::cout << "ptr가 지시하는 값" << *ptr << std::endl;
std::cout << "ptr2가 지시하는 값" << *ptr << std::endl;
}
const_cast로 상수 특성을 해제해서 값을 변경합니다.
이 연산자가 필요한 이유는 대부분의 시간에는 상수로 존재하지만 이따금 값을 바꾸어 주야 하는 경우가 있기 때문입니다.
강제 형 변환을 통하여 바꾸는 거보다 const_cast로 바꾸는 게 더 안전합니다.
이때 주의할 점은, const나 volatile이 있느냐 없느냐에 따라 달라지는 것만 빼고는, 데이터형이 동일해야 합니다.
static_cast
static_cast 연산자도 다른 연산자들과 동일한 문법을 사용합니다.
타입이 가리키는 객체의 데이터형으로 암시적인 변환이 될 수 있을 때 변환됩니다.
즉 업캐스트, 다운캐스트는 되지만 클래스 계층에서 상관없는 클래스로는 변환이 불가능합니다.
#include <iostream>
class Animal {
};
class Dog : public Animal {
};
class Car {
};
int main(void) {
Animal animal;
Dog dog;
Animal * ptr_animal = static_cast<Animal *>(&dog); //업캐스트
Dog * ptr_dog = static_cast<Dog *>(&animal); //다운캐스트
Car * ptr_car = static_cast<Car *>(&animal); //에러!!
}
마찬가지로 열거 값은 데이터형 변환이 없어도 정수 값으로 변환할 수 있기 때문에, static_cast를 사용하여 정수 값을 열거 값으로 변환될 수 있습니다.
double을 int로 변환하거나, float을 long형으로 변환하는 다른 수치 변환도 수행할 수 있습니다.
reinterpret_cast
원래 위험한 데이터형 변환을 하기 위해서 있습니다.
문법은 다른 연산자와 동일합니다.
#include <iostream>
struct test {
short a;
short b;
};
int main(void) {
int a = 1000000;
test * tes = reinterpret_cast<test *>(&a);
std::cout << tes->a << std::endl; //처음 2바이트 출력
}
애초에 위험한 데이터형 변환을 안 하려고 노력하면 됩니다.
이러한 데이터형 변환은 저수준 프로그래밍에서 사용합니다.
댓글