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바이트 출력
}

애초에 위험한 데이터형 변환을 안 하려고 노력하면 됩니다.

이러한 데이터형 변환은 저수준 프로그래밍에서 사용합니다.

 

댓글을 달아 주세요