[OOP] C++ RTTI(Run Time Type Information)

세동네·2022년 6월 21일
0
post-thumbnail
post-custom-banner

C++에선 런타임에 기초 클래스의 객체 포인터가 어떤 객체를 가리키고 있는지 정보를 알려주는 RTTI 기능을 제공한다.

객체지향에선 클래스 간 상속을 구현할 수 있고, 다형성을 가지게 되어 기초 클래스(Base class)는 자신의 멤버를 위임한 파생 클래스(Derived class)를 자신의 객체 포인터로 가리킬 수 있다.

Base *pBase = new Derived();

하지만 컴파일 당시에는 pBase가 어떤 객체를 가리키고 있는지 알 수 없다. 그저 가상 함수 테이블 vftable에 저장된 함수 주소가 무엇인지에 따라서만 기초 클래스와 파생 클래스 중 어떤 객체를 가리키고 있는지 짐작할 수만 있다.

하지만 그 자체가 정보로 주어지는 것도 아니기 때문에 프로그램은 실행 중에 포인터가 가리키고 있는 객체 타입을 명확하게 알 수가 없다. 이러한 정보를 알려주는 것이 RTTI이고, 현재 객체 포인터가 가리키고 있는 객체 타입 정보를 type_info라는 이름으로 vftable에 저장한다.

vftable에 저장한다는 것에서 유추할 수 있지만 RTTI 기능을 사용할 객체는 vftable이 존재하는 즉, 가상 함수를 가진 클래스여야 한다는 것이다.

이러한 RTTI를 활용하는 대표적인 예시는 다음과 같다.

· dynamic_cast()

dynamic_cast()는 다운 캐스팅에서 자주 사용되는 함수이다. 사용 중이던 객체 포인터를 특정 타입으로 변환하여 저장하고 싶을 수 있다.

Base *pBase = new Base();
Derived *pDerived = dynamic_cast<Derived *>(pBase);	// return nullptr

위와 같은 형태로 dynamic_cast()를 사용할 수 있지만, 해당 코드는 정상적으로 실행되지 않는다. 애초에 pBasenew BaseBase 클래스 타입인데 Derived 클래스로 변환할 방법이 없는 것이다.

처음부터 pBaseDerived 클래스를 업 캐스팅하였다면 얘기는 달라진다.

Base *pBase = new Derived();
Derived *pDerived = dynamic_cast<Derived *>(pBase);

pBase 객체는 본래 Derived였던 것을 업 캐스팅한 것이기 때문에 다시 원래 형태로 돌아갈 수 있다. 위에서 본 틀린 코드의 주석을 보면 포인터 타입의 0을 의미하는 널 포인터 nullptr을 반환한다고 되어 있는데, 이 때문에 다음과 같은 예외 처리가 가능하다.

if(pDerived = dynamic<Derived *>(pBase)){
	pDerived->print();
}
else{
	std::cout << "Failed cast to [Derived]" << std::endl;
    exit(0);
}

비슷한 형태로 위의 예외 처리를 이용하면 하나의 기초 클래스에 여러 파생 클래스가 있을 때 서로 다른 파생 클래스 타입으로 다운 캐스팅하는 것을 방지하는 것도 가능하다.

· typeid 연산자

typeid(object) 연산자의 매개변수로 변수 타입이나 객체가 들어갈 수 있으며, 타입의 정보를 담고 있는 클래스 type_info를 반환한다.

· type_info 클래스

시스템에 존재하는 타입들의 정보를 담고 있는 클래스로, 다음과 같은 메서드를 제공한다.

  • name()
    타입의 이름을 반환한다.

    std::cout << typeid(pBase).name() << std::endl;
    ===================== 출력 =====================
     class Base * __ptr64
  • operator ==, !=
    두 타입이 동일한지 검사한다.

    // ==, !=을 사용하는 방법
    
    typeid(Base) == typeid(Derived);	// 또는 !=
    typeid(Base).hash_code() == typeid(Derived).hash_code();	// 또는 !=

· 참고

RTTI
[furyheimdall.tistory.com] RTTI
C++ dynamic_cast에 대해서
[Microsoft Document] type_info 클래스
C++ RTTI(Run Time Type Information), typeid, type_info

post-custom-banner

0개의 댓글