Runtime Type Information
RTTI란
- C++ 컴파일러 내에 있는 객체의 타입 정보를 알아내는 기능
- 런타임에서 포인터가 가리키는 객체의 타입을 알 수 있게 해주는 방법
- 객체의 타입을 런타임에서 결정할 수 있도록 허용
- 메모리 상주 객체에 타입 정보 추가
- 런타임에서 객체의 캐스팅이 유효한지 알아내기 위해, 객체를 특정 타입으로 결정한다
- 가상 함수를 가지고 있는 클래스에 대해서 사용 가능
- vtable을 참조해서 적절한 타입의 클래스를 확인해야 하기 때문
RTTI의 목적
- 하나의 공통 기초 클래스로부터 상속된 클래스 계층이 있다고 가정할 때, 이 계층에 속한 클래스들의 어떤 객체를 기초 클래스 포인터가 지시하도록 설정할 수 있다
- 런타임에서 A 타입에서 B 타입으로 변경할 때 정보가 필요하기 때문
- 컴파일시간에 타입 변환이 이루어진다면 RTTI가 필요없다.
- 컴파일 단계에서 특정 타입으로 확정할 수 있고 그 타입을 확인할 수 있기 때문이다.
예제
// case 1
// 가상함수가 없는 경우
#include <iostream>
class Base { void C() {} };
class MAN : public Base { void A() {} };
class WOMAN : public Base { void B() {} };
int main()
{
Base* base_m = new MAN();
Base* base_w = new WOMAN();
// 아래 코드는 둘다 class Base를 출력한다
cout << typeid(*base_m).name();
cout << typeid(*base_w).name();
return 0;
}
- 위의 코드의 경우, virtual로 선언된 함수가 없으므로 가상 함수 테이블에 없어 RTTI 정보를 가질 수 없다
- 단형성 클래스들의 상속 계층일 뿐
// case 2
// 가상 함수가 있는 경우
#include <iostream>
class Base
{
void C() {}
virtual void GO() {}
};
class MAN : public Base
{
void A() {}
virtual void GO() {}
};
class WOMAN : public Base
{
void B() {}
virtual void GO() {}
};
// 위의 class 들이 virtual method를 가지게 되었다.
int main()
{
Base* base_m = new MAN();
Base* base_w = new WOMAN();
// class WOMAN 출력
std::cout << typeid(*base_w).name() << std::endl;
// class MAN 출력
std::cout << typeid(*base_m).name() << std::endl;
return 0;
}
dynamic_cast
- 다형 형식을 변환하는 데 사용
- 포인터가 지시하는 객체형이 무엇인지는 알려주지 않음
- 그 객체 주소를 특정형의 포인터에 안전하게 대입가능한지 알려줌
typeid
- 개체의 정확한 형식을 식별하는 데 사용
- 두 객체의 데이터형이 같은지 확인 가능
- 객체의 데이터형을 식별하는 하나의 값을 반환함으로서 확인
- 클래스의 이름, 객체로 평가되는 식(??) 등
typeinfo
- typeid 연산자에서 변환된 형식 정보를 저장하는 데 사용
- 어떤 특별한 데이터형에 대한 정보를 저장
- 데이터형을 비교할 수 있도록 ==와 != 연산자 오버로딩
- typeinfo.h 헤더 포함해야 사용 가능