컴퓨터공학/C++

[C++] 캐스팅 4가지

Pyxis 2024. 11. 9. 17:47

[ C++ : 캐스팅 4가지 ]

 

용도에 따라 4가지로 나뉜다. (int)같은 고전적인 C타입 캐스팅은 가장 강력한 캐스팅.
Player를 상속받는 Knight, Archer가 각각 있다고 가정하자.

[1] static_cast<>
타입 원칙에 비춰볼 때, 상식적인 캐스팅만 허용해준다.
1) int <-> float (통상적인 형변환)
2) Player* -> Knight* (위험하긴 하지만, 상속관계에서의 다운캐스팅)
안정성은 보장하지 않는다.
Player* p를 Knight*로 캐스팅하려 할 때, p의 본체가 Knight인 것을 알 수 있을 때만 캐스팅해야 한다.

예시)
1) Player* p = new Knight();
우리가 무엇을 하는지는 알고 있다. 본체는 Knight이기 때문에 안전할 것. (Knight는 Player가 맞으므로)
2) Knight* k1 = static_cast<Knight*> p;

만약 Player* p의 본체가 이전에 업캐스팅됐었던 Archer라면, static_cast<> 이므로 캐스팅은 성공하겠지만, 완전히 잘못된 된 캐스팅이 되는 것이다. 이걸 접근해서 사용하면 클래스가 다르므로 만약 Knight의 크기가 Archer보다 크다면 경계를 넘어선 엉뚱한 메모리에 접근하게 되는 것이다.
만약 p가 함수 밖 멀리에서 넘어온 것이라면, p의 본체가 어떤 것인지 알기 힘들 것이다.

* 테크닉 : Dynamic_cast를 써도 되지만, p에다가 플레이어 타입이라는 것을 넣어줘서 본체가 Archer, Knight 중 어떤 것인지에 대한 추가적인 정보를 넣어주고 그 값을 체크한 다음에, 값에 따라 static_cast<>를 거쳐도 된다.

[2] dynamic_cast<>
상속관계에서의 안전한 형변환
RTTI를 이용 (RunTime Type Information) : 다형성을 활용하는 방식
virtual function이 하나라도 있어야 사용가능하다. 만약 없다면, 에러를 뱉는다. (""는 다형형식이 아닙니다.)
virtual function을 하나라도 만든다면, virtual table이 만들어지기 때문이다.
만약 잘못된 타입으로 캐스팅을 시도한다면, nullptr을 반환.

static_cast<>를 사용하면 메모리 오염이 일어날 수 있는 반면, dynamic_cast<>는 RTTI, 가상 함수 테이블을 통해 본체가 어떤 타입인지 계속 추적 하고 있기 때문에 p가 Knight*인지 아닌지 한번 더 확인을 해주고, 아니라면 nullptr을 반환.
RTTI를 이용하기 때문에 느리다. 상속 레벨(트리 높이)에 성능 영향을 받을 수 있다.

[3] const_cast<>
const를 붙이거나, 없앨 때 사용하는 캐스팅
외부 라이브러리의 함수를 가져와서 쓸 때, 수정이 불가능하므로 인자를 char*를 받으려고할 때, "abc"를 넘기려고하면 const char*이므로 에러가 뜬다.
(char*)를 쓰면 되겠지만 c스타일 캐스팅이므로 const를 떼어주겠다는 의미를 전달하기 위해 사용

[4] reinterpret_cast<>
가장 위험하고 강력한 형태의 캐스팅
포인터랑 전혀 관계없는 다른 타입으로 변환 등, 상관없는 클래스 포인터끼리도 가능 (Knight, Dog)
→ 의도를 표시
malloc같은 경우 void* p = malloc(1000);
라고 요청을하면 반환형이 void*인데, 이것을 Dog*로 변환할려고
Dog* dog2 = p;를 하면 연관성이 없으므로 통과가 되지 않음.
이런 상황에 c스타일 캐스팅 (Dog*)보다 reinterpret_cast<>를 쓰는 것.

 

 

 

 

 

[ Reference ]

Rookiss, Part1. C++ 프로그래밍 입문

'컴퓨터공학 > C++' 카테고리의 다른 글

[C++] using  (0) 2024.11.09
[C++] noexcept  (0) 2024.11.09
[C++] std::move()  (0) 2024.11.09
[C++] 전방 선언  (0) 2024.11.05
[C++] 템플릿 기초  (0) 2024.11.05