class CBase
{
public:
CBase(){}
virtual ~CBase(){}
};
class CDerived : public CBase
{
public:
void Render();
CDerived(){}
~CDerived(){}
};
class CDerived2 : public CBase
{
public:
void Draw();
CDerived2(){}
~CDerived2(){}
}
int main()
{
CBase* pObj = new CDerived;
pObj -> Render(); 오버라이딩 되지 않은 함수 실행 불가
((CDerived*)pObj)->Render(); 실행가능
((CDerived2*)pObj)->Draw(); 실행가능
}
C스타일의 형변환으로도 자식 클래스의 함수를 실행 할 수 있지만 다형성과는 아무런 관련이 없는 위험한 방식이다.
**<주의> 상대적으로 안전한 캐스팅만 있을 뿐 캐스팅은 위험요소가 있음
**C++의 캐스팅 연산자
static_cast : 컴파일 타임에 캐스팅을 수행(정적 캐스팅), 논리적인 형변환을 해주며 C스타일의 캐스팅과 거의 같지만 좀 더 안전하다.
int iNum = static_cast<int>(3.14f);
장점 : 컴파일 타임에 캐스팅을 수행하기 때문에 동작 속도가 빠름
단점 : 런 타임에 발생하는 보안, 문법적 오류를 확인 할 수 없음
dynamic_cast : 다운 캐스팅을 하기 위한 목적, 다형성을 사용하기 위한 캐스팅, 일반 자료형은 캐스팅불가
조건
1. 클래스가 상속 관계에 있어야 함.
2. 부모 클래스에 가상 함수가 한 개라도 있어야 함.
장점 : 런 타임시, 비 논리적인 형 변환을 발견하게 되면 nullptr 반환하기 때문에 예외처리를 할 수 있다.
단점 : 캐스팅 속도가 느림.
class CBase
{
public:
CBase(){}
virtual ~CBase(){}
};
class CDerived : public CBase
{
public:
void Render();
CDerived(){}
~CDerived(){}
};
int main()
{
CBase* pDer = new CDerived
dynamic_cast<CDerived*>(CDerived)->Render();
}
가상 함수가 있어야 하는 이유 : '가상 함수 테이블'을 참조하여 함수를 실행하기 때문에 가상 함수 테이블 생성을 위해 가상 함수가 있어야 함(하다못해 소멸자라도)
const_cast : 포인터나 레퍼런스에 부여된 const 성질을 벗겨내기 위한 도구
int iNum = 10;
const int* p = &iNum;
int *p2 = const_cast<int*>(p);
*p2 = 20;
reinterpret_cast : const 포인터 제외 모든 포인터의 형 변환을 허용
예측 할 수 없는 동작을 할 수 있기 때문에 사용을 권장하지 않는다.
int iNum = 65;
char* ptr = reinterpret_cast<char*>(&iNum);
**TMI
RTTI (Run Time Type Information)