[C++] 캐스팅: static, dynamic, const, reinterpret cast
캐스팅 4총사 (static, dynamic, const, reinterpret cast)
인프런 Rookiss님의 'Part1: C++ 프로그래밍 입문' 강의를 기반으로 정리한 필기입니다.
😎[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강의 들으러 가기!
cast의 종류 : static cast, dynamic cast, const cast, reinterpret cast
static cast
- static cast는 컴파일 타임에 진행된다.
- 타입 변환에 자주 사용. 다운 캐스팅, 업 캐스팅 시 사용 가능.
- Cast 시 안전 검사를 하지 않는다.
dynamic cast
- RTTI를 기반으로 런타임에 적용한다.
- cast로 클래스 간 Up, Down cast에 자주 사용되며 cast 시 안전 검사를 한다.
const cast
- 변수에 const 속성을 등록 및 해제하기 위해 사용하는 cast다. (= const를 붙이거나 떼거나 할 때 사용한다.)
reinterpret cast
- 포인터 간 변환을 위해 사용하는 cast다.
- 임의의 포인터 객체를 다른 포인터 객체로 변환할 수 있다. 이러한 변환은 안전하지 않을 수 있기 때문에 주의가 필요하다.
※ C++에서는 가상 함수(virtual function)을 사용하여 런타임 다형성을 구현할 수 있으므로 업캐스팅(Up Casting) 없이도 객체 타입에 따라 올바른 함수가 호출될 수 있다. 따라서 cast를 명시적으로 사용하는것 보다 가상 함수를 사용하는 것이 더 좋다.
1. static _cast
static_cast : 타입 원칙에 비춰볼 때 상식적인 캐스팅만 허용해준다. 4가지 cast 방식 중 가장 많이 활용한다.
static_cast 사용 경우: 1. 타입 변환, 2. 다운캐스팅(Down Casting), 3. 업캐스팅(Up Casting)
1) 타입 변환
- int <-> float
2) 다운캐스팅(Down Casting)
- 다운캐스팅은 '부모클래스->자식클래스', 단, 안전성 보장 못함
- Player* -> Knight*
3) 업캐스팅(Up Casting)
- 잘 사용하지 않음.
- '자식->부모' 이기 때문에 굳이 캐스팅을 하지 않아도 문제가 되지 않는 경우가 대부분이다.
#include <iostream> using namespace std; class Player { }; class Knight : public Player { }; class Archer : public Player { }; int main() { int hp = 100; int maxHp = 200; // float ratio = hp / maxHp // 인수 나눗셈이어서 0.5가 아닌 0으로 출력된다 // float ratio = (float)hp / maxHp; // float에서 int를 나누면 float가 우선순위가 높아서 실수로 나온다 float ratio = static_cast<float>(hp) / maxHp; // 다운캐스팅. C++ 친화적인 문법 // 자식->부모 : 굳이 캐스팅이 필요가 없다 Knight* k = new Knight(); Player* p2 = k; // 캐스팅을 하지 않아도 문제가 되지 않는다 // 부모->자식 Player* p = new Knight(); // Knight* k1 = (Knight*)p; // (Knight*)p는 c스타일 타입변환 Knight* k1 = static_cast<Knight*>(p); // 좀 더 정확한 의미 // 부모->자식, 다운캐스팅이 문제되는 상황 Player* p = new Archer(); Knight* k1 = static_cast<Knight*>(p); k1-> //포인터로 접근해서 값을 고치면 엉뚱한 메모리를 고치는 상황이 발생할 수 있다. return 0; }
2. dynamic_cast
dynamic_cast : 상속 관계에서의 안전 형변환
RTTI (RunTime Type Information)
- 다형성을 활용하는 방식
- 런타임 중 타입을 확인할 수 있다.
dynamic_cast를 사용하려면 virtual 함수가 필요하다.
- virtual 함수를 하나라도 만들면, 객체의 메모리에 가상 함수 테이블 (vftable) 주소가 기입된다.
- 만약 잘못된 타입으로 캐스팅을 했으면, nullptr 반환한다. dynamic_cast의 경우 RTTI의 가상 함수 테이블(vftable)를 활용하여 자신이 어떤 애인지 확인하기 때문에 잘못된 타입으로 변환하면, nullptr로 반환한다. (반면에 static_cast는 메모리오염이 발생한다.)
- 이를 이용해서 맞는 타입으로 캐스팅을 했는지 확인을 유용하다.
- static_cast보다 느리다.

↑ virtual 함수가 하나도 없으면 위의 이미지와 같은 에러 문구를 띄우며 빌드가 되지 않는다.
#include <iostream> using namespace std; class Player { public: virtual ~Player() { } }; class Knight : public Player { }; class Archer : public Player { }; class Dog { }; int main() { Player* p = new Knight(); Knight* k2 = dynamic_cast<Knight*>(p); return 0; }
nullptr 반환 예시 코드
#include <iostream> using namespace std; class Player { public: virtual ~Player() { } }; class Knight : public Player { }; class Archer : public Player { }; class Dog { }; int main() { Player* p = new Archer(); Knight* k2 = dynamic_cast<Knight*>(p); // 잘못된 타입으로 캐스팅한 경우. nullptr 반환 return 0; }

3. const_cast
const_cast : const를 붙이거나 떼거나 할 때 사용한다.
사용 예시: 공동 작업을 할 때 누군가 const로 값 변화를 막아두었을때, 값을 변화시켜 테스팅하고 싶을 때 사용한다.
#include <iostream> using namespace std; void PrintName(char* str) { cout << str << endl; } int main() { // 공동 작업 시 PrintName 함수를 수정하면 안 되는 상황 PrintName("Rookiss"); // const char* 형이기 때문에 통과 안됨 PrintName((char*)"Rookiss") // c스타일의 타입변환. 통과는 되지만 추천하지 않는 방식 PrintName(const_cast<char*>("Say my name")); // c++ 스타일. const_cast return 0; }

4. reinterpret_cast
reinterpret_cast는 포인터랑 전혀 관계없는 다른 타입 변환 등에 사용한다.
- 가장 위험하고 강력한 형태의 캐스팅
- 're-interpret' : 다시-간주하다/생각하다.
- 사용 예시:
- void* p = malloc(1000);
- 해당 경우에 malloc은 void*로 반환한다.
- Dog* dog2 = reinterpret_cast<Dog*>(p);로 써서 void*형을 사용하여 Dog로 만들어주겠다.
#include <iostream> using namespace std; class Player { public: virtual ~Player() { } }; class Knight : public Player { }; class Archer : public Player { }; class Dog { }; int main() { Knight* k2 = dynamic_cast<Knight*>(p); __int64 address = (__int64)(k2); // c스타일 캐스팅 __int64 address = reinterpret_cast<__int64>(k2); // c++ reinterpret_cast Dog* dog1 = reinterpret_cast<Dog*>(k2); // Knight와 Dog는 상관관계가 없지만 reinterpret_cast 할 수 있다. void* p = malloc(1000); // void*형으로 1000byte를 할당하겠다. // 할당한 메모리를 Dog* 형으로 사용하겠다. Dog* dog2 = p; // 통과 안됨 Dog* dog2 = (Dog*)p; // c스타일 캐스팅. (Dog*)는 사용하는 경우가 많아 실수의 여지가 높다. Dog* dog2 = reinterpret_cast<Dog*>(p); return 0; }
언리얼 cast

'⭐ Programming > C++' 카테고리의 다른 글
[C++] 함수 포인터 1 (0) | 2022.04.15 |
---|---|
[C++] 전방선언 (0) | 2022.04.12 |
[C++] 얕은 복사 vs 깊은 복사 2 (0) | 2022.04.10 |
[C++] 얕은 복사 vs 깊은 복사 1 (0) | 2022.04.09 |
[C++] 타입 변환 4: 포인터 (0) | 2022.04.09 |
댓글
이 글 공유하기
다른 글
-
[C++] 함수 포인터 1
[C++] 함수 포인터 1
2022.04.15함수 포인터 1 인프런 Rookiss님의 'Part1: C++ 프로그래밍 입문' 강의를 기반으로 정리한 필기입니다. 😎[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강의 들으러 가기! 포인터 int main() { int a = 10; // 바구니 주소 // pointer[ 주소 ] -> 주소 [ ] typedef int DATA; // 1) 포인터 * // 2) 변수 이름 pointer // 3) 데이터 타입 int DATA* pointer = &a; // 함수 typedef int(FUNC_TYPE)(int a, int b); using FUNC_TYPE = int(int a, int b); } 함수 포인터 함수 포인터는 함수를 가리키는 포인터다. 반환… -
[C++] 전방선언
[C++] 전방선언
2022.04.12전방선언 인프런 Rookiss님의 'Part1: C++ 프로그래밍 입문' 강의를 기반으로 정리한 필기입니다. 😎[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강의 들으러 가기! 헤더 추가 ver. vs. 전방선언 Ver1. 헤더를 추가하여 클래스 정보를 불러오는 방법 - #include로 헤더를 추가한다. - 클래스 사이즈만큼 불러온다. - 클래스 사이즈만큼 불러오기 때문에 클래스의 크기가 크면 메모리 소모가 크다. Ver2. 전방선언을 하고 참조 형태로 가지고 오는 방법 - class 클래스명 형식으로 전방선언한다. - 클래스를 참조해서 데이터를 사용한다. - 포인터 사이즈만큼만 메모리가 필요하다. (32bit 운영체제는 4byte, 64bit 운영체제는… -
[C++] 얕은 복사 vs 깊은 복사 2
[C++] 얕은 복사 vs 깊은 복사 2
2022.04.10얕은 복사 vs 깊은 복사 2 인프런 Rookiss님의 'Part1: C++ 프로그래밍 입문' 강의를 기반으로 정리한 필기입니다. 😎[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강의 들으러 가기! 1. 암시적 복사 생성자 Steps 1) 부모 클래스의 복사 생성자 호출 2) 멤버 클래스의 복사 생성자 호출 3) 멤버가 기본 타입일 경우 메모리 복사 (얕은 복사 Shallow Copy) 더보기 #include using namespace std; // 얕은 복사 vs 깊은 복사 2 class Pet{ public: Pet() { cout -
[C++] 얕은 복사 vs 깊은 복사 1
[C++] 얕은 복사 vs 깊은 복사 1
2022.04.09얕은 복사 vs 깊은 복사 1 인프런 Rookiss님의 'Part1: C++ 프로그래밍 입문' 강의를 기반으로 정리한 필기입니다. 😎[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강의 들으러 가기! 목차 기본 #include using namespace std; class Pet { public: Pet() { cout
댓글을 사용할 수 없습니다.