Run Time Type Information
의 약자로
프로그램 실행 중에 포인터가 가르키는 객체의 타입을 알 수 있게 해주는 방법이다
RTTI
가 필요한 이유는 상속 관계에서 발생하는 타입 변환 시에
virtual 클래스로 상속받는 경우 컴파일 시간에 추적이 불가능하기 때문이다
(virtual 클래스를 제외한 일반적인 상속관계에서 발생하는 타입은 컴파일 시간에 해석됨)
dynamic_cast의 경우 RTTI
에 의존적이며,
초기엔 static_cast 분석을 사용하고 불가능하면 RTTI
를 사용하는 구조로 설계되어있다.
#include <iostream>
class Parent {
public:
virtual void print() {
std::cout << "parent" << std::endl;
}
};
class Child : public Parent {
private:
int num;
public:
Child(int _num) {
num = _num;
}
virtual void print() {
std::cout << "child" << std::endl;
}
void print_num() {
std::cout << "num: " << this->num << std::endl;
}
};
void new_cast(Parent* p) {
p->print();
Child* c = (Child*)p;
c->print_num();
}
int main() {
Parent p;
Child c(5);
new_cast(&c);
new_cast(&p);
}
여기서 결과는 아래와 같이 나왔으나,
만약 virtual 함수가 없었다면, 타입 추적이 안되기 때문에 child가 parent로 출력된다.
result :
child
num: 5
parent
num: -858993460
RTTI가 제대로 동작하기 위해선 모든 클래스에 타입과 관련된 정보를 작성해야 한다.
이렇다보니 프로그램이 느려지고 용량이 커지는 문제가 있어 RTTI 기능을 사용할 것인지 아닌지에 대한 옵션이 따로 존재한다.
'클래스의 이름', '객체', '객체를 가르키는 포인터'를 피연산자로 취하며 피연산자의 타입을 조사한다.
// typeinfo 헤더 파일
class type_info {
public:
virtual ~type_info();
int operator ==(const type_info& rhs) const;
int operaotr !=(const type_info& rhs) const;
int before(const type_info& rhs) const;
// 문자열도 된 타입의 이름(클래스 이름)을 조사
const char* name() const;
// 장식명을 조사(사람이 읽을 수 없는 문자열), 비교에만 사용
const char* raw_name() const;
private:
void* _m_data;
char _m_d_name[1];
type_info(const type_info& rhs);
type_info& operator =(const type_info& rhs);
};
#include <iostream>
#include <typeinfo>
class Parent {
public:
virtual void print() {
std::cout << "parent" << std::endl;
}
};
class Child : public Parent {
public:
virtual void print() {
std::cout << "child" << std::endl;
}
};
int main() {
Parent P, *pP;
Child C, *pC;
pP = &P;
pC = &C;
std::cout << typeid(P).name() << std::endl; // class Parent
std::cout << typeid(pP).name() << std::endl; // class Parent *
std::cout << typeid(*pP).name() << std::endl; // class parent
std::cout << typeid(C).name() << std::endl; // class Child
std::cout << typeid(pC).name() << std::endl; // class Child *
std::cout << typeid(*pC).name() << std::endl; // class Child
return 0;
}