런타임 유형 정보

Run-time type information

컴퓨터 프로그래밍에서 런타임 유형 정보 또는 런타임 유형 식별(RTTI)[1]런타임에 개체의 데이터 유형에 대한 정보를 노출하는 일부 프로그래밍 언어(C++,[2] Object Pascal, Ada[3] 등)의 기능이다.런타임 유형 정보는 모든 유형에 대해 또는 명시적으로 해당 정보가 있는 유형에만 사용할 수 있다(Ada의 경우처럼).런타임 유형 정보는 유형 내성이라고 불리는 보다 일반적인 개념의 전문화다.

원래의 C++ 디자인에서 Bjarne Strustrup은 런타임 타입 정보를 포함하지 않았다. 왜냐하면 그는 이러한 메커니즘이 종종 잘못 사용된다고 생각했기 때문이다.[4]

개요

C++에서는 RTTI를 사용하여 안전한 타입캐스트를 수행할 수 있으며,dynamic_cast<>연산자 및 런타임에 를 사용하여 유형 정보를 조작하는 방법typeid운영자 및std::type_infoclass. Object Pascal에서 RTTI를 사용하여 안전 유형 캐스트를 수행할 수 있다.as연산자, 객체가 속한 클래스를 테스트한다.is연산자, 그리고 에 포함된 클래스로 런타임에 유형 정보를 조작한다.RTTI단위[5](즉, 클래스:TRTtiContext, TRTtiInstanceType 등).Ada에서 태그가 지정된 유형의 개체도 유형 태그를 저장하므로 런타임에 이러한 개체 유형을 식별할 수 있다.in운영자는 런타임에 객체가 특정 유형이고 안전하게 변환될 수 있는지 테스트하는 데 사용할 수 있다.[6]

RTTI는 다형성인 클래스에만 사용할 수 있으며, 이는 그들이 적어도 하나의 가상 방법을 가지고 있다는 것을 의미한다.기본 클래스에 가상 소멸자가 있어야 파생 클래스의 객체가 기본 포인터에서 삭제될 경우 적절한 정리를 수행할 수 있기 때문에 이는 제한이 아니다.

일부 컴파일러에는 RTTI를 비활성화하는 플래그가 있다.이러한 플래그를 사용하면 애플리케이션의 전체 크기를 줄일 수 있어 메모리가 제한된 시스템을 대상으로 할 때 특히 유용할 수 있다.[7]

C++ – typeid

typeid 키워드런타임객체클래스를 결정하는 데 사용된다.대한 참조를 반환한다.std::type_info프로그램이 끝날 때까지 존재하는 개체.[8]의 사용typeid, 비동형적 맥락에서, 종종 보다 선호된다.dynamic_cast<class_type>단지 수업정보가 필요한 상황에서, 왜냐하면typeid항상 일정한 시간 절차인 반면,dynamic_cast런타임에 해당 인수의 클래스 파생 격자를 통과해야 할 수 있다.[citation needed]반환되는 객체의 일부 측면은 다음과 같이 구현이 정의된다.std::type_info::name(), 그리고 일관성을 유지하기 위해 여러 컴파일러에 의존할 수 없다.

클래스 객체std::bad_typeid라는 표현이 나올 때 내동댕이쳐진다.typeidNull 포인터에 단항 * 연산자를 적용한 결과 입니다.다른 null 참조 인수에 대해 예외를 적용할지 여부는 구현에 의존한다.즉 예외를 보장받으려면 그 표현이 형식을 취해야 한다는 것이다.typeid(*p)어디에pnull 포인터를 생성하는 식입니다.

#include <아이오스트림> #include <타입인포>  계급 사람 { 공중의:     가상의 ~사람() = 체납; };  계급 직원 : 공중의 사람 {};  인트로 본래의() {     사람 사람;     직원 종업원;     사람* 삐걱삐걱거리다 = &종업원;     사람& 참조하다 = 종업원;          // typeid::name으로 반환되는 문자열은 구현 정의됨.     찌꺼기::뻐드렁니가 나다 << 활자의(사람).이름을 붙이다()               << 찌꺼기::끝을 맺다;  // 사용자(컴파일 시간에 정적으로 알려져 있음).     찌꺼기::뻐드렁니가 나다 << 활자의(종업원).이름을 붙이다()               << 찌꺼기::끝을 맺다;  // 직원(컴파일 시간에 정적으로 알려져 있음).     찌꺼기::뻐드렁니가 나다 << 활자의(삐걱삐걱거리다).이름을 붙이다()               << 찌꺼기::끝을 맺다;  // Person*(컴파일 시간에 정적으로 알려져 있음).     찌꺼기::뻐드렁니가 나다 << 활자의(*삐걱삐걱거리다).이름을 붙이다()               << 찌꺼기::끝을 맺다;  // 직원(런타임에서 동적으로 검색됨                              // 왜냐하면 그것은 a의 불합격이기 때문이다.                              // 다형성 클래스를 가리키는 포인터).     찌꺼기::뻐드렁니가 나다 << 활자의(참조하다).이름을 붙이다()               << 찌꺼기::끝을 맺다;  // 직원(참조도 다형성일 수 있음)      사람* p = 무효의;          해보다 {         활자의(*p); // 정의되지 않은 동작, std::bad_typeid를 던짐.     } 잡히다 (...) { }      사람& p_ref = *p; // 정의되지 않은 동작: 비참조 null     활자의(p_ref);      // std 던지기 요구 사항을 충족하지 않음:bad_typeid                         // typeid에 대한 식이 결과가 아니기 때문에                         // 단항 * 연산자 적용. } 

출력(정확한 출력은 시스템 및 컴파일러에 따라 다름):

Personal Person* 직원* 직원

C++ – Dynamic_cast 및 Java 캐스트

dynamic_castC++의 연산자는 참조 또는 포인터를 클래스 계층 구조에서 보다 구체적인 유형으로 다운캐스트하는 데 사용된다.이전과 달리static_cast, 의 대상dynamic_cast클래스에 대한 포인터 또는 참조여야 한다.와는 달리static_castC형 타입캐스트(편찬 중 타입 체크를 하는 경우), 타입 안전 점검은 런타임에 실시한다.형식이 호환되지 않으면 예외가 발생(참조 처리 시)되거나 null 포인터가 반환(포인터 처리 시)된다.

Java typecast도 비슷하게 동작한다. 캐스트되는 객체가 실제로 대상 유형의 인스턴스가 아니며 언어 정의 방법에 의해 하나의 인스턴스로 변환될 수 없는 경우,java.lang.ClassCastException내동댕이쳐질 것이다.[9]

일부 함수가 유형 객체를 사용한다고 가정해 보십시오.A그 논거로서, 그리고 만약 전달된 물체가 의 예일 경우, 약간의 추가 작업을 수행하기를 원한다.B, 의 하위 클래스A이 작업은 다음을 사용하여 수행할 수 있다.dynamic_cast아래와 같이

#include <배열> #include <아이오스트림> #include <기억> #include <타입인포>  사용. 네임스페이스 찌꺼기;  계급 A { 공중의:     // RTTI는 가상 방법 표에 포함되므로     // 하나 이상의 가상 기능.     가상의 ~A() = 체납;      공허하게 하다 Method SpecificToa() {         뻐드렁니가 나다 << "A에 대한 특정 방법이 호출됨" << 끝을 맺다;     } };  계급 B: 공중의 A { 공중의:     공허하게 하다 Method SpecificToB() {         뻐드렁니가 나다 << "B에 대한 특정 방법이 호출됨" << 끝을 맺다;     } };  공허하게 하다 MyFunction(A& my_a) {     해보다 {         // B형 객체에 대해서만 캐스팅이 성공한다.         B& my_b = 다이나믹_캐스트<B&>(my_a);         my_b.Method SpecificToB();     } 잡히다 (경시하다 bad_cast& e) {         귀리 << " 예외 " << e.무엇() << " 던져졌다." << 끝을 맺다;         귀리 << "개체가 B 유형이 아님" << 끝을 맺다;     } }  인트로 본래의() {     배열하다<유니크_ptr<A>, 3> array_of_a; // 기본 클래스 A에 대한 포인터 배열     array_of_a[0] = make_make<B>();   // B 물체에 대한 포인터.     array_of_a[1] = make_make<B>();   // B 물체에 대한 포인터.     array_of_a[2] = make_make<A>();   // A 객체에 대한 포인터.      을 위해 (인트로 i = 0; i < 3; ++i)         MyFunction(*array_of_a[i]); } 

콘솔 출력:

B에 대한 특정 메서드가 호출됨 B에 대한 특정 메서드가 호출됨 예외 std::bad_cast 던짐.개체가 B 유형이 아님

의 유사한 버전MyFunction참조 대신 포인터를 사용하여 쓸 수 있음:

공허하게 하다 MyFunction(A* my_a) {     B* my_b = 다이나믹_캐스트<B*>(my_a);      만일 (my_b != 무효의)         my_b->Method SpecificToB();     다른         찌꺼기::귀리 << "개체가 B 유형이 아님" << 찌꺼기::끝을 맺다; } 

델파이 / 오브젝트 파스칼

Object Pascal에서 연산자is런타임에 클래스의 유형을 확인하는 데 사용된다.상속 계층 트리에 존재하는 개별 선조들의 계층을 포함하여 주어진 계층에 대한 개체의 소속을 테스트한다(예: 버튼1TWinControlTControl → TControl → TCombentTCPersistentTCObject). 여기서 후자는 모든 계층의 조상이다.오퍼레이터as어떤 물체가 마치 조상 계급에 속하는 것처럼 런타임에 처리되어야 할 때 사용된다.

RTTI 단위는 런타임에 객체 유형 정보를 조작하는 데 사용된다.이 단위에는 다음과 같은 작업을 수행할 수 있는 클래스 집합이 포함되어 있다: 어떤 개체의 클래스와 그 조상, 속성, 방법 및 이벤트, 속성 값 및 호출 방법 변경.다음 예제는 RTTI 모듈을 사용하여 객체가 속하는 클래스에 대한 정보를 얻고, 객체를 생성하며, 그 방법을 호출하는 것을 보여준다.이 예에서는 TSubject 클래스가 SubjectUnit이라는 유닛에서 선언되었다고 가정한다.

사용하다   RTTI, 제목유닛;  절차 심사숙고하지 않고, 경솔하게; 시합을 하다   MySubject: TSubject; 시작되다   MySubject := TSubject.만들다;   해보다     제목.안녕;   종국에는     제목.무료;   종지부를 찍다; 종지부를 찍다;  절차 반성과 함께; 시합을 하다   RttiContext: TRTtiContext;   릿티타입: TRTtiInstanceType;   제목: 토버젝트; 시작되다   릿티타입 := RttiContext.FindType('SubjectUnit.TSubject') 로서 TRTtiInstanceType;   제목 := 릿티타입.겟메토드('만들기').호출하다(릿티타입.메타클라스유형, []).AsObject;   해보다     릿티타입.겟메토드('여보세요').호출하다(제목, []);   종국에는     제목.무료;   종지부를 찍다; 종지부를 찍다; 

참고 항목

참조

  1. ^ Sun Microsystems (2000). "Runtime Type Identification". C++ Programming Guide. Oracle. Retrieved 16 April 2015.
  2. ^ "Language support library [support.rtti]". eel.is. Retrieved 2021-07-13.
  3. ^ "Object-oriented programming". learn.adacore.com. Retrieved 2021-07-13.
  4. ^ Bjarne Stroustrup (March 1993). "A History of C++: 1979—1991" (PDF). Bjarne Stroustrup. p. 50. Retrieved 2009-05-18.
  5. ^ "Working with RTTI - RAD Studio". docwiki.embarcadero.com. Retrieved 2021-06-06.
  6. ^ English, John (2002-02-22). "Chapter 15". Ada 95: The Craft of Object-Oriented Programming. Retrieved 2021-07-13.
  7. ^ "Avoiding RTTI, and support for -fno-rtti in Arm Compiler 6". Arm Developer. Retrieved 2021-07-13.
  8. ^ C++ 표준 (ISO/IEC14882) 섹션 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
  9. ^ "ClassCastException (Java Platform SE 8 )".

외부 링크