[Refactoring] 3. 캐스팅
- 컴퓨터공학과/그외
- 2015. 11. 18.
이번에는 캐스팅에 대해서 공부합니다.
3. 캐스팅
퀴즈퀴즈!
char* pa = malloc(sizeof(char)); // c(o), c++(x)
char* pb = (char*)malloc(sizeof(char)); // c(o), c++(o)
위의 두 문장은 C, C++ 환경에서 문제없이 잘 돌아갈까요?
(정답은 질문 옆을 아주 잘~ 보면 보입니다.)
C언어에서는 명시적으로 형 변환을 하지 않아도
컴파일러는 알아서 잘 짰거니 하고, 개발자를 믿고 실행합니다.
논리적으로 잘못됐어도 에러를 내지 않으니 개발자는 월화수목금금금...
이와 달리,
C++에서는 타입 체크가 강화되어 타입을 명시하지 않으면 컴파일 에러가 납니다.
♥ 따라서 C++에서는 타입을 정확히 명시해주어야 합니다.
그러나 (char*) 이런 식으로 명시적 캐스팅 연산자를 쓰는 건 벧스멜~~(냄시)
이런 캐스팅은 컴파일러가 타입 체크하는 기능을 꺼버리기 때문입니다.
♥ 컴파일러가 체크하게끔 하라!!
하여 4가지 캐스팅에 대해 살펴보겠습니다.
1) static_cast
C++은 명시적인 형변환 연산자를 사용하면 안 됩니다.
이는 컴파일러의 타입 체크 기능을 끄게 하기 때문입니다.
>>> static_cast : 이상적 형 변환에 사용
char *pc = static_cast<char*>(malloc(sizeof(char)));
static_cast는 인스턴스 되기 전에, 컴파일 타임에 캐스팅 됩니다.
컴파일러가 캐스팅을 책임지지요.
2) reinterpret_cast
int x = 0x1;
char *p = &x;
x는 int인데 char형 포인터를 사용할 경우 (unresonable이라고 표현합니다.)
C언어에선 문제없지만, C++에서는 타입 체크가 강하기 때문에
포인터의 타입이 달라 에러를 냅니다.
빅엔디안인지 리틀 엔디안인지 확인해 보는 경우와 같이
의도적으로 비이상적인 코딩을 해야 할 경우에도,
C++에서는 에러가 내어
개발자가 의도적으로 사용하고 싶어도 쓰지 못하게 됩니다. 흑흑 (static_cast도 마찬가지!)
이는 컴파일러가 비이상적이라고 생각했기 때문입니다.
이러한 경우에!
비이상적인 형 변환을 하고자 한다면, reinterpret_cast 사용하면 됩니다.
reinterpret_cast는 비이상적 형 변환을 지원합니다.
char *p = reinterpret_cast<char*>(&x);
3) const_cast
const double PI = 3.14;
double* p = &PI;
const 상수를 사용하였으므로
논리적으로 변환이 되지 않도록 하는 것이 맞지만
그럼에도 불구하고 변환을 해야 할 때가 있습니다.
이럴 때,
논리적 상수성을 깨려면 const_cast를 사용합니다.
double* p = const_cast<double*>(&PI);
** const_cast를 쓴다는 것은 const 상수 설계가 제대로 되지 않은 경우가 많다.
가급적이면 쓰지마!라고 하십니다.
4) dynamic_cast
이번엔 Animal클래스를 살펴봅시다.
22 라인의 Animal* p = &d;
는 Animal과 Dog의 타입이 달라 statc_cast 캐스팅하여
Animal *p = static_cast<Animal*>(&d);
로 써야하는 거 아닌ㄱㅏ여??????
라고 물으신다면 대답해드리는 게 인지상정!
♥ Upcasting 시, 상속 관계에 있을 때는 캐스팅 연산자 생략 가능합니다.
컴파일 시에 두 클래스 간의 관계를 알고 있기 때문입니다.
따라서 static_cast를 쓰지 않아도 Animal* p = &d;로 표현 가능한 것이죠.
그렇다면 다운 캐스팅은 어떠할까요?
Animal을 Dog로 다운 캐스팅하는
Dog* pDog = p; 는 불가능합니다.
♥ Downcasting에서는 연산자를 생략할 수 없습니다.
부모의 타입을 자신의 타입으로, 안전한 다운 캐스팅을 하고 싶다면 dynamic_cast 연산자를 사용해야 합니다.
Dog* pDog = dynamic_cast<Dog*>(p);
주의해야할 것은,
dynamic_cast는 컴파일에 체크되지 않으므로 런타임에 체크해야한다는 것입니다.
if( pDog != 0)
cout << "Dog" << endl;
else
cout << "!Dog" << endl;
static_cast : 이상적 형 변환에 사용
reinterpret_cast : 비이상적 형 변환에 사용
const_cast : 상수 변환에 사용
dynamic_cast : 다운 캐스팅에 사용
'컴퓨터공학과 > 그외' 카테고리의 다른 글
[Refactoring] 5. 널 객체 (0) | 2015.11.18 |
---|---|
[Refactoring] 4. 상속 (0) | 2015.11.18 |
[Refactoring] 2. 인터페이스 (0) | 2015.10.29 |
[Refactoring] 1. 순수 가상함수와 추상 클래스 (0) | 2015.10.29 |
Top 10 IT Trends for 2015 (0) | 2015.06.29 |