오늘은 C++의 캐스트 연산자에 대해 알아보겠다.
01. static_cast
c언어의 형변환과 유사하다.
double d = 5.5;
int n = static_cast<int>(d);
C에서는 n = (int)d;
실수형에서 정수형으로 형변환을 하였다.
당연히 소수점 부분은 잘려버리게 된다.
하지만 컴파일러가 허용하는 범위이기 때문에 가능.
![](//i1.daumcdn.net/deco/contents/emoticon/things_13.gif?v=2)
stirng str = "abcd";
int n = static_cast<int>(str);
string을 int로 바꾸고 있다.
이 경우는 컴퍼일러가 허용하지 않는다.
그리고 static_cast는 포인터 형변환이 안된다.
int n = 10;
int *pi;
double *pd;
pi = &n;
pd = static_cast<double*>(&n);
이런 식으로의 포인터 형변환은 되지 않는다.
![](//i1.daumcdn.net/deco/contents/emoticon/things_11.gif?v=2)
포인터 형변환이 의미가 있는 경우는
클래스 상속과 연관될 때이다.
class AAA{
public:
int na;
};
calss BBB : public AAA {
public:
int nb;
};
AAA a;
AAA *pa;
BBB b;
BBB *pb;
pa = static_cast<AAA*>(&b); 1번
pb = static_cast<BBB*>(&a); 2번
2번의 경우 Base 클래스 자료형의 값을
Drieved 클래스 자료형에 할당하고 있기 때문에
다운 캐스팅을 하는 경우이다. 1번은 2번과
반대의 경우인 업 캐스팅을 하는 경우이다.
업캐스팅의 경우에는 문제가 안되지만
다운캐스팅의 경우에는 문제가 생긴다.
![](//i1.daumcdn.net/deco/contents/emoticon/things_17.gif?v=2)
1번의 경우 pa가 Drived 객체에 있는 멤버에
접근을 하지 못하지만 문제가 되진 않는다.
하지만 2번의 경우 즉 다운캐스팅이 된 경우를 보자.
Drived 클래스에는 Base에는 없는데 자신만 가지고 있는
멤버의 존재가 가능하다. 이 경우 원래 존재하지도 않는
값을 참조하게 될 수 있다는 문제가 발생한다.
pb -> nb; 같은 식으로 말이다.
![](//i1.daumcdn.net/deco/contents/emoticon/things_14.gif?v=2)
02. dynamic_cast
위와 같은 문제 때문에 나타난 것이 바로 dynamic_cast이다.
상속 관계에 있는 클래스 포인터끼리의 형변환을 허용하되,
다운 캐스팅이 일어나면 null 값을 대신 리턴하여 위험을 알린다.
따라서 이 형변환을 사용할 때는 먼저 결과가 null이
아닌지 확인하는 것이 좋다. 또한 이 형변환을 사용하기 위해서는
클래스가 다형성을 가져야 한다. 가상함수가 있어야 한다는 말.
class AAA{
public:
virtual void print() { cout<<"부모 객체"<<endl }
};
class BBB : public AAA{
public:
virtual void print() { cout<<"자식 객체"<<endl }
};
![](//i1.daumcdn.net/deco/contents/emoticon/things_11.gif?v=2)
AAA aaa;
AAA *pa;
BBB bbb;
BBB *pb;
1번
pa = dtnamic_cast<AAA*>(&aaa);
if(pa) pa->printf();
else cout<<"캐스팅 실패"<<endl;
2번
pa = dtnamic_cast<AAA*>(&bbb);
if(pa) pa->printf();
else cout<<"캐스팅 실패"<<endl;
3번
pb = dtnamic_cast<AAA*>(&aaa);
if(pa) pa->printf();
else cout<<"캐스팅 실패"<<endl;
4번
pb = dtnamic_cast<AAA*>(pa);
if(pa) pa->printf();
else cout<<"캐스팅 실패"<<endl;
![](//i1.daumcdn.net/deco/contents/emoticon/things_16.gif?v=2)
1번의 경우 당연히 성공
2번의 경우도 당연히 성공 (다형성의 중요한 부분)
3번의 경우 다운캐스팅이기 때문에 실패한다.
4번의 경우 Base 형 포인터의 값을 가져왔으나
그게 사실 Drived 형 객체를 가리키기 때문에 성공.
따라서 위의 결과는
부모 객체
자식 객체
캐스팅 실패
자식 객체
![](//i1.daumcdn.net/deco/contents/emoticon/things_09.gif?v=2)
위에서 살펴본 형변환의 이점은 가독성과 디버깅의 편리함이다.
dynamic_cast는 엉뚱한 다운캐스팅으로 인한 오류를
경우에 따라 훨씬 빨리 찾아내는게 가능해진다.