MFC를 쓰며 언제나 "저게 뭐야?"하고 지나쳐왔던 RUNTIME_CLASS, DECLARE_DYNAMIC등의 매크로. 어디에, 왜, 언제쓰는지도 모른 채 그냥 지나쳐왔던 그 내용들..이것들이 실행 시 인스턴스의 실제 타입을 알아내는 데 이용하는 MFC의 메카니즘이라는 것을 이제야 알게되었다. 그것도 MFC가 아니라, C++을 다시 보면서.

RTTI(Run-Time Type Identification 혹은 Run-Time Type Information)은 C++에서 기본적으로 지원한다. 근디, MFC에서는 C++이 지원하는 놈들을 안쓰고 위의 매크로 등을 통해 독자적으로 이 기능을 지원하는데, 왜 그런지는 낭중에 알아보기로 해야겠다. (새로 배우기도 빡신데, 찾기까지는 넘 힘들다.) Visual C++에서는 프로젝트 Setting 항목에서 C++ Language 탭의 "Enable RTTI"를 활성화해야 한다.
  • dynamic_cast 연산자
  • : 기반 클래스의 포인터를 통해 파생 클래스의 함수를 불러내야할 경우, 그 함수가 기반 클래스에 없는 비가상(non-virtual) 함수라면, virtual 메카니즘으로는 해결이 안된다. 바로 이 경우에, 기반 클래스의 포인터를 이 연산자로써 캐스트해서 불러내면 되더라.

    • 어떤 클래스 객체에 대한 포인터를, 그 클래스와 동일한 계통에 있는 다른 클래스의 포인터로 변경할 경우에 사용하거나, 어떤 클래스 객체에 대한 lvalue를, 그 클래스와 동일한 계통에 있는 다른 클래스의 레퍼런스로 변경할 경우에 사용한다.

    • 다른 캐스트 연산자와는 달리, 런타임에 변환이 되고, 올바른 변환인지를 검사한다음, 올바를 경우에만 변환하기 때문에 다른 캐스트 연산자보다 안전하더라..
    • 변환 실패의 경우, 포인터 타입에 대한 실패일 때는 0을 반환, 레퍼런스 타입에 대한 실패일 때는 예외를 던진다. 고로 언제나 변환 성공 여부에 대한 TEST 코드를 넣는 것이 신상에 좋더라..(예외 타입인 std:bad_cast를 참조하려면, <typeinfo> 헤더를 포함해야 한다.)

    예: employee가 manager의 기반 클래스일 때(pE는 employee의 포인터, rE는 레퍼런스),
    1 : manager* pM = dynamic_cast< manager* >(pE); // 포인터 타입의 변환
    2 : manager& rM = dynamic_cast< manager& >(rE); // 레퍼런스 타입의 변환

  • typeid 연산자 : 표현식(expression)으로써 타입이 무엇인지를 알아낼 수 있다. 여기서 표현식은 일반 타입이 될 수 있고, 가상 함수가 담긴 타입도 될 수 있는데, 그 표현식의 결과는 표현식 자체의 타입에 따라 달라지더라...

    • <typeinfo> 헤더를 포함해야 한다.

    • 이 연산자의 반환 값은 type_info 클래스 타입이더라..

    • 주로, type_info 클래스의 name() 함수(표현식의 타입 이름을 반환)와 == 연산자를 많이 이용하더라..


  • type_info 클래스 : typeid 연산자가 반환하는 타입. 이 타입을 이용해서 타입 비교, 타입 이름 알아내기 등을 해낸다.

    • <typeinfo> 헤더를 포함해야 한다.

    • 기본 생성자는 없으며, 복사 생성자와 복사 대입 연산자가 private 멤버이기 때문에, 사용자가 자신의 프로그램에서 따로 정의해서 사용할 수 없다. 오직 typeid 연산자를 통해서만 생성된다.

    • 컴파일러마다 각기 달리 구현된다. 그러므로, 타입 이름 외에도 컴파일러에 따라 다른 종류의 정보가 담겨질 수 있다.


참고 자료 : C++ Primer(Stan Lippman저, Addison-Wesley)
반응형
Posted by 어쨌건간에

댓글을 달아 주세요