업캐스팅
- 파생 클래스의 객체를 기본 클래스의 포인터로 가리키는 것
- 쉽게 말해, 자식 클래스 객체를 부모 클래스의 포인터로 가리키는 것
 - 파생 클래스의 객체를 기본 클래스 객체처럼 다룰 수 있다.
 
 
#include <iostream>
#include <string>
using namespace std;
class Circle // 기본 클래스
{
public:
	int radius;
public:
	void setRadius(int r)
	{
		radius = r;
	}
    
	void showRadius()
	{
		cout << "반지름" << radius << endl;
	}
};
class Pizza : public Circle // 파생 클래스
{
public:
	double getArea();
};
double Pizza::getArea() 
{
	return radius * radius*3.14;
}
int main()
{
	Circle circle;
	circle.setRadius(5);
	circle.showRadius();
	Pizza Hampizza;
	Hampizza.setRadius(10);
	cout << "햄 피자면적:" << Hampizza.getArea() << endl;
	Pizza cheesepizza;
	Pizza* cDer = &cheesepizza;
	Circle* cBase = cDer; //업 캐스팅 (자식클래스 객체 cDer 를 부모클래스 포인터가 가리키고있다)
	cBase->setRadius(100);
	cout << "치즈 피자면적:" << cDer->getArea() << endl;
	cBase->getArea(); // 오류 발생
    
    /*
    cBase는 Circle 클래스의 포인터이므로 cBase 포인터로는 Circle 클래스 멤버만 접근할 수 있다.
	그러므로 getArea() 함수는 Circle 클래스의 멤버가 아니므로 오류가 발생한다.
    */
}
다운캐스팅
- 기본 클래스 포인터가 가리키는 객체를 파생 클래스의 포인터로 가리키는 것을 다운 캐스팅 이라한다.
- 쉽게 말해, 부모 클래스가 가리키는 객체를 자식 클래스의 포인터로 가리키는 것.
 - 자식 형식에서 부모 형식을 사용하는 것이며 업캐스팅에서 다시 원래의 형으로 되돌려주는 작업이다.
 - 다운 캐스팅은 업 캐스팅과 달리 명시적 타입 변환을 지정해야 한다.
 
 
#include <iostream>
#include <string>
using namespace std;
class Circle  // 기본 클래스
{
public:
	int radius;
public:
	void setRadius(int r)
	{
		radius = r;
	}
	void showRadius()
	{
		cout << "반지름" << radius << endl;
	}
};
class Pizza : public Circle // 부모 클래스
{
public:
	
	double getArea();
};
double Pizza::getArea()
{
	return radius * radius*3.14;
}
int main()
{
	Circle circle;
	circle.setRadius(5);
	circle.showRadius();
	Pizza Hampizza;
	Hampizza.setRadius(10);
	cout << "햄 피자면적:" << Hampizza.getArea() << endl;
	Pizza cheesepizza;
	Pizza* cDer = &cheesepizza;
	Circle* cBase = cDer; // 업 캐스팅
	cBase->setRadius(100);
	cBase->showRadius();
	
	cDer = (Pizza*)cBase; //다운 캐스팅: 부모 클래스가 가리키는 객체를 자식 클래스의 포인터로 가리키는 것.
	cDer->setRadius(1);
	cDer->showRadius();
	cout << "치즈 피자면적:" << cDer->getArea() << endl;
	
}
static_cast
- static_cast<바꾸려고 하는 타입>(대상);
 - 기본 자료형의 형변환 및 기본(base) 클래스에서 파생(derived) 클래스로의 포인터 변환 연산에 사용할 수 있다.
형 변환 시점이 컴파일 시점이기 때문에 static 이라는 명칭이 붙는다.
- 프로그램이 실행되는 동안 (dynamic) 변환하는게 아닌, 컴파일러가 컴파일하면서 변환 시 오류를 발생시킬지 판단하는 정적인 타입 변환이라는 의미.
 - 주로 부모 클래스로 업 캐스팅 해주는 연산자.
- 물론 다운 캐스팅도 가능하지만, 부모 클래스 객체를 자식 클래스 포인터로 변환하면 메모리 구조가 다를 수 있어 **정의되지 않은 동작(UB)**이 발생할 수 있으므로, 다운캐스팅은 dynamic_cast를 사용하는 것이 안전.
 
 
 - static_cast를 사용하는 이유
- 실수형과 정수형, 정수형과 열거형등의 기본 데이터 타입 간의 변환
 - 상속관계의 클래스 계층 간의 변환
 - void 포인터를 다른 타입의 포인터로 변환
 - 서로 다른 타입의 포인터 간의 타입 변환은 못함
 
- 런타임 타입 검사를 하지 않음 → 런타임 검사는 dynamic_cast 를 사용해야함
 - 아형성이 없어도 변환가능(RTTI - 런타임 타입 정보 옵션이 꺼져있어도 된다.)
- 아형성(subtype) : 기본 - 파생 클래스 간의 관계를 의미함.
 - 기본 - 파생 간 상속관계가 없어도, 강제로 타입 변환을 할 수 있다는 의미.
 - 즉, RTTI 가 꺼져있어도 강제 변환이 되므로, 실제 타입 안정성을 보장할 수 없다.
 
 - 다중 상속에서 기본 클래 간의 타입 변환은 못함
- 부모1, 부모2, 자식 다중상속일 때, 부모1, 2 는 서로 직접적인 관계가 없다.
 - 따라서 static_cast 로 부모1을 부모2로 변환하거나 반대인 경우에도 컴파일 에러가 발생한다.
 - 이런 경우는 명시적 타입 변환 or dynamic_cast를 할 수 있다.
 
 
 
dynamic_cast
- dynamic_cast<변환 타입>(대상);
 - 상속 관계에 놓여 있는 두 클래스 사이에서, 파생(derived) 클래스의 포인터 및 참조형 데이터를 기본(base) 클래스의 포인터 및 참조형 데이터로 형 변환하는 경우.
- 부모 클래스의 포인터에서 자식 클래스의 포인터로 다운 캐스팅 해주는 연산자
 
 - dynamic_cast를 사용하는 이유
- dynamic_cast는 런타임에 타입을 검사하여 안전한 다운캐스팅을 보장하는 C++ 연산자입니다.
주된 이유는 다운캐스팅(Downcasting)을 안전하게 수행하기 위해서입니다. 
 - dynamic_cast는 런타임에 타입을 검사하여 안전한 다운캐스팅을 보장하는 C++ 연산자입니다.
 - static_cast 와의 차이
- static_cast는 컴파일 타임에 타입 변환을 수행하지만, dynamic_cast는 런타임에 타입 검사를 수행.
 - static_cast는 잘못된 변환이 있어도 컴파일은 통과하지만, 런타임 오류가 발생할 수 있음.
 - dynamic_cast는 잘못된 변환이 있을 경우 nullptr을 반환하거나 std::bad_cast 예외를 던짐
 
 - dyanamic_cast 의 사용조건
- RTTI (런타임 타입 정보) 활성화 되어있어야 함.
 - Virtual Function을 사용.
- 그 이유는 RTTI의 type_info 때문.
- virtual function을 사용하게 되면 해당 클래스에는 v-table이 생성.
- 이 v-table에는 override된 자식 클래스의 함수를 가르킬 수 있는 주소값이 들어있는데 이 v-table에 클래스의 type_info 정보가 들어감.
 
 
 - virtual function을 사용하게 되면 해당 클래스에는 v-table이 생성.
 
 - 그 이유는 RTTI의 type_info 때문.
 - 위 이유들로 인해, dynamic_cast를 사용하게 되면 좀 더 안전한 형변환 가능.
 
 - RTTI (런타임 타입 정보) 활성화 되어있어야 함.
 - 제약사항
- RTTI는 자원을 좀 먹기 때문에 퍼포먼스 측면에서 static_cast보다 좀 떨어진다.
 
 
reinterpret_cast
- reinterpret_cast<변환 타입>(대상);
 - 가장 강력한 캐스팅 연산자.
- 임의의 포인터 타입끼리 변환을 허용함.
 - 형 변환시, 변환 타입 자료형의 비트 수에 맞게 들어가게 된다.
 - 포인터 to 포인터 / 포인터 to 변수 / 변수 to 포인터 모두 가능. (자료형 to 자료형은 안됨)
 
 - 가장 위험한 캐스팅 연산자이기도 함.
- 정수형을 포인터로 바꿔버릴 수도 있지만, 정수값이 포인터의 절대 주소로 들어가므로 위험함.
 - 정수형 포인터를 char 로 바꾸면, char (1바이트) 가 int *(4바이트) 보다 크기가 작기 때문에, 원본데이터가 파괴된다.
 
 - reinterpret_cast를 사용하는 이유
- (void *) 로 전달이 가능하기에 특수한 경우에 사용된다.
 - 주로 네트워크 패킷 관련된 곳에서 사용되는데, 일반적으론 권장하지 않는 캐스팅.
 
 
const_cast
- const_cast<변환 타입>(대상);
 - 포인터나 참조형의 상수성(const) 를 잠시 제거해주거나, volatile 키워드를 잠깐 제거해주는 캐스팅.
- const로 선언된 변수를 가리키는 포인터 변수가 있으면, const 변수는 유지하면서 포인터만 잠시 제거해주는 역할.
- 원본 const 변수는 그대로 유지되므로 안전함.
 
 - 일반적인 타입변환용 캐스팅은 아니다.
 
 - const로 선언된 변수를 가리키는 포인터 변수가 있으면, const 변수는 유지하면서 포인터만 잠시 제거해주는 역할.
 - const_cast 의 사용조건
- const로 선언된 포인터만 const를 풀어줄 수 있다.
 - 포인터가 아닌 일반 변수의 const는 풀어줄 수 없다.
 - 함수 포인터, 멤버 함수에 대한 const는 풀어줄 수 없다.
 
 
[참고자료]
윤성우의 열혈 C++
modoo의 씹어먹는 C++
https://hwan-shell.tistory.com/213
C++] dynamic_cast에 대해서...
모든 언어에는 형변환이 있습니다. C++에선 다양한 형번환 객체들을 제공합니다. 1. static_cast = https://hwan-shell.tistory.com/211 2. dynamic_cast 3. const_cast = https://hwan-shell.tistory.com/215 4. reinterpret_cast = https://
hwan-shell.tistory.com
https://blockdmask.tistory.com/240
[C++] const_cast (타입 캐스트 연산자)
안녕하세요. BlockDMask 입니다.오늘은 C++ 의 네가지 타입 캐스트 연산자 중에 (static_cast, const_cast, reinterpret_cast, dynamic_cast) const_cast 에 대해 알아보겠습니다.> const_cast 에 관한 기본 특성const_cast(expres
blockdmask.tistory.com