[Refactoring] 3. 캐스팅

이번에는 캐스팅에 대해서 공부합니다.



3. 캐스팅

퀴즈퀴즈!


char* pa = malloc(sizeof(char));              // c(o), c++(x)

char* pb = (char*)malloc(sizeof(char));      // c(o), c++(o)

위의 두 문장은 C, C++ 환경에서 문제없이 잘 돌아갈까요?


(정답은 질문 옆을 아주 잘~ 보면 보입니다.)



C언어에서는 명시적으로 형 변환을 하지 않아도 

컴파일러는 알아서 잘 짰거니 하고, 개발자를 믿고 실행합니다.

논리적으로 잘못됐어도 에러를 내지 않으니 개발자는 월화수목금금금...crying



이와 달리, 

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 : 다운 캐스팅에 사용


이상 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

댓글

❤️김세인트가 사랑으로 키웁니다❤️