{{위키데이터 속성 추적}}
'''런타임 타입 정보'''(RTTI, Run-Time Type Information 또는 Run-Time Type Identification<ref>Sun Microsystems (2000)</ref>)는 [[런타임]] 시 객체의 [[자료형]]에 관한 정보를 드러내는 [[C++]] 메커니즘을 가리킨다. RTTI는 간단한 정수나 문자와 같은 자료형 또는 제네릭 타입에 적용할 수 있다. 이것은 [[타입 인트로스펙션]]이라고 부르는 더 일반적인 개념의 C++ 특수화이다. 델파이 ([[오브젝트 파스칼]])같은 다른 프로그래밍 언어들에서도 비슷한 메카니즘이 존재한다.

원래 C++ 디자인에서, [[비야네 스트롭스트룹]]은 이 메커니즘이 자주 오용된다고 생각했기 때문에,  RTTI를 포함시키지 않았다.<ref>[[비야네 스트롭스트룹]]</ref>

== 개요 ==
<code>dynamic_cast<></code> 연산과  <code>typeid</code> 연산자가 C++에서 RTTI를 구성한다. C++ 런타임 타입 정보는 런타임시에 안전한 [[형 변환]]과 타입 조작의 수행을 허용한다. RTTI는 오직 [[다형성|다형적인]] 클래스들에서 사용가능한데, 이것은 적어도 하나의 [[가상 함수]]를 갖는다는 것을 의미한다. 실제로 이 점은 만약 이것들이 베이스 포인터에서 지워진 경우, 베이스 클래스들은 (반드시 상속받은 클래스들의 객체들이 적절한 클린업을 수행하게 하는) [[가상 함수|가상 소멸자]]를 가져야 하기 때문에 한계라고 할 수 없다. RTTI는 어떤 컴파일러들에서는 선택사항이다; 프로그래머는 컴파일 시에 함수를 포함할 지를 선택할 수 있다. 프로그램은 이것을 사용하지 않더라도 RTTI를 사용가능하게 만들 리소스 비용이 존재할 것이다.

== typeid ==
<code>typeid</code> [[예약어|키워드]]는 런타임 시에 [[객체 (컴퓨터 과학)|객체]]의 [[클래스 (컴퓨터 과학)|클래스]]를 선택하는데 사용된다. 이것은 <code>std::type_info</code> 객체에 대한 참조를 반환하는데, 프로그램의 종료 시까지 존재하게 된다.<ref>C++ standard (ISO/IEC14882) section 5.2.8 [expr.typeid], 18.5.1 [lib.type.info] -- http://cs.nyu.edu/courses/fall11/CSCI-GA.2110-003/documents/c++2003std.pdf {{웨이백|url=http://cs.nyu.edu/courses/fall11/CSCI-GA.2110-003/documents/c++2003std.pdf |date=20160305010557 }}</ref> 다형성이 사용되지 않은 문맥에서 단지 클래스 정보가 필요한 경우 <code>typeid</code>의 사용은 종종 <code>dynamic_cast<''class_type''></code> 보다 선호된다. 왜냐하면 <code>dynamic_cast</code>가 반드시 런타임시에 이것의 인자의 클래스 상속 래티스를 순회해야하는 반면, <code>typeid</code>는 시상수 프로시저이기 때문이다. 반환된 객체의 어떤 면들은 <code>std::type_info::name()</code> 처럼 구현 시에 정의되며, 모든 컴파일러들에서 일정하다고 할 수는 없다.

클래스 <code>std::bad_typeid</code>의 객체들은 [[널 포인터]]에서 <code>typeid</code>를 위한 표현이 <code>unary *</code> 연산자를 적용하는 것의 결과일 때 던져진다. 예외가 다른 널 참조 인자에 던져지든지 말든지는 구현에 종속적이다. 즉, <code>p</code>가 널 포인터를 야기하는 어느 표현일 때, 보장되어야 할 예외를 위해 표현은 반드시 <code>typeid(*p)</code> 형태를 취해야 한다.

=== 예시 ===
<syntaxhighlight lang="cpp">
#include <iostream>    // cout
#include <typeinfo>    // for 'typeid'

class Person {
public:
   virtual ~Person() {}
};

class Employee : public Person {
};

int main()
{
   Person person;
   Employee employee;
   Person* ptr = &employee;
   Person& ref = employee;
   // The string returned by typeid::name is implementation-defined
   std::cout << typeid(person).name() << std::endl;   // Person (statically known at compile-time)
   std::cout << typeid(employee).name() << std::endl; // Employee (statically known at compile-time)
   std::cout << typeid(ptr).name() << std::endl;      // Person* (statically known at compile-time)
   std::cout << typeid(*ptr).name() << std::endl;     // Employee (looked up dynamically at run-time
                                                      //           because it is the dereference of a
                                                      //           pointer to a polymorphic class)
   std::cout << typeid(ref).name() << std::endl;      // Employee (references can also be polymorphic)

   Person* p = nullptr;
   try {
      typeid(*p); // not undefined behavior; throws std::bad_typeid
   }
   catch (...) {
   }

   Person& pRef = *p; // Undefined behavior: dereferencing null
   typeid(pRef);      // does not meet requirements to throw std::bad_typeid
                      // because the expression for typeid is not the result
                      // of applying the unary * operator
}

</syntaxhighlight>결과 (시스템에 따라 정확한 결과는 다르다.):
 Person
 Employee
 Person*
 Employee
 Employee

== dynamic_cast 와Java cast ==
C++의  <code>dynamic_cast</code> 연산자는 클래스 계층에서 참조나 포인터를 더 구체적인 타입으로 다운캐스팅하는데 사용된다.  <code>static_cast</code>와 달리, <code>dynamic_cast</code> 의 대상은 반드시 클래스에 대한 포인터나 참조여야 한다. <code>static_cast</code> 와 [[C (프로그래밍 언어)|C-스타일]] 타입캐스트(타입 검사가 컴파일 시에 이루어지는)와 달리, 타입 안전 검사는 [[런타임]] 시에 수행된다. 만약 타입들이 호환되지 않는다면, 예외가 던져지거나(참조를 다룰 때) [[널 포인터]]가 반환될(포인터를 다룰 때) 것이다.

자바 타입캐스트도 비슷하게 동작한다; 만약 던져진 객체가 실제로 대상 타입의 인스턴스가 아니고, 인스턴스인 언어로 정의된 방식으로 변환되지 못한다면,  <code>java.lang.</code><code>ClassCastException</code> 의 인스턴스가 던져질 것이다.<ref>http://docs.oracle.com/javase/8/docs/api/java/lang/ClassCastException.html</ref>

=== 예시 ===
몇몇 함수가 타입 <code>A</code>의 객체를 인자로 받으며, 만약 전달받은 객체가 <code>B</code>의 인스턴스이고, <code>A</code>의 서브클래스라면, 몇몇 추가적인 연산을 수행하길 바란다고 가정하자. 이것은 다음과 같이 <code>dynamic_cast</code> 를 사용함으로써 달성될 수 있다.<syntaxhighlight lang="cpp">
#include <typeinfo> // For std::bad_cast
#include <iostream> // For std::cout, std::err, std::endl etc.

class A {
public:
    // Since RTTI is included in the virtual method table there should be at least one virtual function.
    virtual ~A() { };
    void methodSpecificToA() { std::cout << "Method specific for A was invoked" << std::endl; };
};

class B : public A {
public:
    void methodSpecificToB() { std::cout << "Method specific for B was invoked" << std::endl; };
    virtual ~B() { };
};

void my_function(A& my_a)
{
    try {
        B& my_b = dynamic_cast<B&>(my_a); // cast will be successful only for B type objects.
        my_b.methodSpecificToB();
    }
    catch (const std::bad_cast& e) {
        std::cerr << "  Exception " << e.what() << " thrown." << std::endl;
        std::cerr << "  Object is not of type B" << std::endl;
    }
}

int main()
{
    A *arrayOfA[3];          // Array of pointers to base class (A)
    arrayOfA[0] = new B();   // Pointer to B object
    arrayOfA[1] = new B();   // Pointer to B object
    arrayOfA[2] = new A();   // Pointer to A object
    for (int i = 0; i < 3; i++) {
        my_function(*arrayOfA[i]);
        delete arrayOfA[i];  // delete object to prevent memory leak
    }
}
</syntaxhighlight>콘솔 결과:
 Method specific for B was invoked
 Method specific for B was invoked
 Exception std::bad_cast thrown.
 Object is not of type B
<code>my_function</code>의 비슷한 버전이 참조 대신 포인터로 쓰여질 수 있다:<syntaxhighlight lang="cpp">
void my_function(A* my_a)
{
    B* my_b = dynamic_cast<B*>(my_a);

    if (my_b != nullptr)
        my_b->methodSpecificToB();
    else
        std::cerr << "  Object is not B type" << std::endl;
}
</syntaxhighlight>

== 같이 보기 ==
* [[반영 (컴퓨터 과학)]]

== 각주 ==
{{각주}}

== 외부 링크 ==
* [https://web.archive.org/web/20060504080540/http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp?topic=%2Fcom.ibm.vacpp6m.doc%2Flanguage%2Fref%2Fclrc05keyword_dynamic_cast.htm <code>dynamic_cast</code> operator at IBM Mac OS X Compilers]
* [https://web.archive.org/web/20080319120439/http://msdn2.microsoft.com/en-us/library/cby9kycs.aspx <code>dynamic_cast</code> operator at MSDN]

[[분류:C++]]
[[분류:자료형]]