● 형변환이란?
원칙은 같은 타입의 변수끼리 연산을 수행하여야 합니다. 그런데 같은 데이터 타입끼리만 연산이 수행될 때가 아닌 경우도 있습니다. 이때 작은 데이터타입의 변수가 다른 큰 쪽 변수의 타입에 맞게 묵시적으로 변형됩니다. 이를 자동형변환 또는 upcasting이라고 합니다.
또는 프로그래머의 의지에 따라 데이터타입을 강제적으로 변환할 수도 있습니다. 이는 보통 데이터범위가 큰 타입을 보다 작은타입으로 변환하는 경우가 대부분이며 이는 강제형변환이라고 또는 downcasting이라고도 합니다.
정리하자면,
형변환이란 특정 데이터타입의 변수를 다른 데이터타입으로 변환하는 것입니다.
- 큰 데이터타입에서 작은 데이터타입으로 변경하는 것을 : downcasting, 강제형변환
- 작은 데이터타입에서 큰 데이터타입으로 변경하는 것을 : upcasting, 자동형변환
다운캐스팅은 보통 강제적, 명시적으로, 업캐스팅은 자동적으로 묵시적으로 이루어집니다.
C언어의 형변환 연산자는
float value;
int a;
a = (int) value;
와 같이 데이터형이 다르지만 임의로 그 데이터형으로 무조건 변환한다 것이 있었는데.
근데 이놈은 이렇게 무분별하게 무조건적인 데이터변환 해싸서 여차하면 실수로 인한 심각한 프로그램 오류를 발생 시키는 좀 위험한 놈이다.
그래서 C++로 넘어오면서 형변환 연산자 들이 새로 나오고 용도가 명확해졌는데 .
그것들은 static_cast , const_cast , dynamic_cast , reinterpret_cast 등이 있다.
● C언어의 형변환 : 만능 형변환 = 무식한 형변환 = 불가능은 없다 ㅡㅡ;;
● static_cast : 가장 기본적인 캐스팅이다.
실수, 정수, 열거형 등 우리가 기본적으로 사용하는 캐스팅이지만 C언어 형태처럼 만능
으로 뭐든지 변환하지는 못하고 약간의 제약사항등이 있다.
사용 예 : 묵시적 변환이 가능한 형변환을 명시적으로 변환한다든지, 수치적인 자료형을 변환한다든
지, void*을 원형으로 변환할 때 사용
사용불가 : 서로 다른 타입의 포인터 간의 타입 변환
서로다른 타입의 포인터간의 변환은 의미 없는 변환이므로 static_cast는 잘못된 형변환으
로컴파일러가 인식합니다
int n = 10; double d = 3.5;
n = d; //암시적 형변환
n = (double)d; // C 스타일의 명시적 형변환
n = static_cast<double>(d); //C++ 스타일의 명시적 형변환
cout << *static_cast<int*>(pv) << endl; // void * 형변환
● const_cast : 상수성을 제거하는데 사용한다
const_cast는 const를 비const화 할 때 사용합니다. 비 const화 할 수 있는 능력의 형변환은 const_cast 뿐입니다.
int *pint = const_cast<int*>(pconstint);
pint = 20;
위와 같이 pint는 상수성이 제거되면서 대상값을 아무 제약없이 변경할 수 있다. (포인터 상수만)
● dynamic_cast : 상속관계 안에서 포인터나 참조자의 타입을 기본클래스에서 파생클래스로 다운캐스
팅과 다중상속에서 기본클래스간의 안전한 타입캐스팅에 사용한다.
실행시간에 부모 형식을 자식 형식으로 다운캐스팅(downcasting) 할 때 사용합니
다. dynamic_cast는 실시간에 형검사를 하거나 형변환할 때 사용합니다. 그리고 다형
성을 지원하기 위해 부모 형식을 자식 형식으로 다운 캐스트하고 형식을 검사합니다
주의사항 : dynamic_cast는 실행 시간에 형변환하여 형변환이 불가능하면 NULL을 반환하고 가능하면 변환합니다. 주의할 점은 다형적인 객체에만(virtual 함수를 포함하는 클래스 객체) dynamic_cast를 사용할 수 있습니다. 당연한 이유로 dynamic_cast는 실행 시간에 정확한 객체 형식을 구분하여 인터페이스를 사용하기 위한(멤버 함수를 호출하기 위한) 목적으로 사용되기 때문입니다.
class A {...};
class B : public A { ... }
A *pBase = new A;
A *pParent = new B;
B *pP = new B;
//pParent = pBase;
pParent = dynamic_cast<B*>( pBase );
//pP = pParent;
pP = dynamic_cast<B*>( pParent );
위에서 주석처리 된 부분은 컴파일 에러가 나는 부분이다.
위와 같이 다이나믹 캐스트는 안전하게 부모 클래스에서 파생클래스로 다운캐스팅을 해준다.
.
● reinterpret_cast : 위 3가지 캐스트가 하지 못하는 잡다한 모든 캐스팅을 한다.
단, 상수형(const) 만은 제거하지 못한다. 클래스간에 상속관계가 성립되지 않거
나 전혀 타입이 다른 어떠한 객체들,,,,, 전혀 상관이 없는 변수간의 타입변환을 수
행할 수 있다.
C++ 스타일의 형변환에서 가장 무식한 형변환입니다. const만 깰 수 없고 C언어의 형변환처럼 모두 가능합니다. 구현 환경(implementation)에 의존적이며 사용할 일이 거의 없습니다.
class Point{
int x, y;
public :
Point(int _x=0, int _y=0):x(_x),y(_y)
{
}
void Print( )
{
cout << x << ", " << y << endl;
}
};
void main( )
{
int n = 10;
reinterpret_cast<Point&>(n); // 오~~ 가능..
reinterpret_cast<Point*>(&n); // 오오~~ 가능..
reinterpret_cast<Point&>(n).Print();// 오오오~~ 가능..
reinterpret_cast<Point*>(n)->Print();// 오오오오~~ 가능.. ㅡㅡ;
}