C ++에서 'typeid'와 'typeof'


159

C ++ typeidtypeofC ++ 의 차이점이 무엇인지 궁금합니다 . 내가 아는 것은 다음과 같습니다.

  • typeidC ++ 헤더 파일 typeinfo에 정의 된 type_info 문서에 언급되어 있습니다.

  • typeofC 및 C ++ Boost 라이브러리 의 GCC 확장에 정의되어 있습니다.

또한, 내가 찾은 곳에서 내가 만든 typeid예상 코드를 반환하지 않는 테스트 코드 테스트가 있습니다. 왜?

main.cpp

#include <iostream>  
#include <typeinfo>  //for 'typeid' to work  

class Person {  
    public:
    // ... Person members ...  
    virtual ~Person() {}  
};  

class Employee : public Person {  
    // ... Employee members ...  
};  

int main () {  
    Person person;  
    Employee employee;  
    Person *ptr = &employee;  
    int t = 3;  

    std::cout << typeid(t).name() << std::endl;  
    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)  
 }  

산출:

bash-3.2$ g++ -Wall main.cpp -o main  
bash-3.2$ ./main   
i  
6Person  
8Employee  
P6Person  
8Employee

8
어떤 방법으로 코드가 올바른 유형 이름을 인쇄하지 않는다고 생각합니까? 나에게 좋아 보인다. 에 의해 반환되는 실제 문자열 name()은 구현 정의입니다. 그것은 올바른 C ++ 식별자 이름, 다만 필요는 없습니다 뭔가 독특한 유형을 식별합니다. 구현에서 컴파일러의 일반 이름 관리 체계를 사용하는 것 같습니다.
Rob Kennedy

고마워 Rob! en.wikipedia.org/wiki/Typeid에서 본 것과 동일한 유형 이름을 기대하고있었습니다. 이름 변환은 무엇을 할 수 있습니까?
Tim

나처럼 typeid를 처음 사용하는 경우 : vtable을 켜려면 기본 유형의 가상 기능이 필요하거나 마지막 줄이 기본 유형을 인쇄합니다.
jw_

답변:


200

C ++ 언어는와 같은 것이 없습니다 typeof. 컴파일러 별 확장을보고 있어야합니다. GCC에 대해 이야기하고 있다면 typeof키워드를 통해 비슷한 기능이 C ++ 11에 decltype있습니다. 다시, C ++에는 그러한 typeof키워드 가 없습니다 .

typeid런타임에 유형 식별 정보를 리턴하는 C ++ 언어 연산자입니다. 기본적으로 type_info다른 type_info객체 와 동등한 객체를 반환 합니다.

반환 된 type_info객체 의 정의 된 유일한 속성은 동일성과 비등가 비교 가능하다는 것입니다. 즉, type_info서로 다른 유형을 type_info설명 하는 객체는 동일 하지 않은 것을 비교해야하지만 동일한 유형을 설명 하는 객체는 동일하게 비교해야합니다. 그 밖의 모든 것은 구현 정의되어 있습니다. 다양한 "이름"을 리턴하는 메소드는 사람이 읽을 수있는 것을 리턴한다고 보장하지 않으며, 아무것도 리턴하지 않을 수도 있습니다.

또한 위의 내용은 표준에 명시 적으로 언급하지 않았지만 typeid동일한 유형 의 연속 응용 프로그램이 다른 type_info객체를 반환 할 수 있음을 의미 합니다 (물론 여전히 동일하게 비교해야 함).


1
C ++ 11이 있기 때문에 업데이트가 필요하지 decltype않습니까? 일반적인 정책이 무엇인지 잘 모르겠지만 질문에 태그가 붙어 C++있으므로 최신 표준을 참조 할 것으로 기대합니다. 질문에 태그를 다시 지정하면 C++03옵션이 될 수도 있습니다. 직장에서 preC ++ 11을 사용해야하므로 때때로 개인적으로 상당히 혼란스러워지고 때로는 "pre11"또는 "post11"이 무엇인지 잘 모르겠습니다.
idclev 463035818

11
참고로 decltype의 대체품이 아닙니다 typeof. 그렇지 않은 typeof동안 유형에서도 작동합니다 decltype. 예를 들어, typeof(int)int동안 decltype(int)오류이다.
Shahbaz

1
" type_info다른 유형을 설명하는 객체는 동일하지 않습니다 . " 실제로 이것은 보장되지 않습니다 . 불평등 연산자는 C ++ 20에서 제거되어 동일하지 않은 비교하는 다른 유형에 의존하지 않습니다. 그러나 당신이 그것에 대해 생각하면, 불평등이 안전하지 않으면 평등은 안전하지 않습니다.
인디애나 Kernick

51

이 둘의 주요 차이점은 다음과 같습니다.

  • typeof는 컴파일 타임 구문이며 컴파일 타임에 정의 된대로 형식을 반환합니다.
  • typeid는 런타임 구성이므로 값의 런타임 유형에 대한 정보를 제공합니다.

typeof 참조 : http://www.delorie.com/gnu/docs/gcc/gcc_36.html

typeid 참조 : https://en.wikipedia.org/wiki/Typeid


감사합니다, JaredPar! 답글을 읽은 후 업데이트 된 게시물에 새로운 질문이 있습니다. 예를 들어, 그들의 반환이 다른 목적으로 사용되는 것이 사실이라면 : typeof의 반환은 변수를 정의 할 수있는 type 키워드로 사용되지만 typeid의 반환은 불가능합니까?
Tim

26

typeidRTTI (런타임 유형 정보) 를 클래스에 저장 하려면 런타임시 작동하고 객체의 런타임 유형을 설명하는 객체를 반환 할 수 있습니다. 또한 런타임 유형 정보가있는 클래스에 대한 포인터가 제공되지 않은 경우 컴파일 시간 유형의 표현식 또는 유형 이름을 제공 할 수 있습니다.

typeofGNU 확장이며 컴파일 타임에 모든 표현 유형을 제공합니다. 예를 들어, 여러 유형에 사용될 수있는 매크로에서 임시 변수를 선언하는 데 유용 할 수 있습니다. C ++에서는 일반적으로 템플릿을 대신 사용 합니다.


5
내가 아는 typeid한 가상 메서드를 사용하여 객체로 평가되는 표현뿐만 아니라 모든 표현을 받아 들일 것입니다. 또한 표현식뿐만 아니라 typeidtype name 도 허용합니다 . 당신이 말 typeid(5)하거나 typeid(std::string)원하는 경우 말할 수 있습니다 .
Rob Kennedy

1
나는 그것을 명확하게하기 위해 나의 대답을 명확히했다; typeid 사용 가능한 경우 런타임에게 유형 정보를 반환하지만, 무엇을위한 컴파일시의 형태 정보를 제공합니다.
Brian Campbell

Brian과 Rob에게 감사합니다! 답글을 읽은 후 업데이트 된 게시물에 새로운 질문이 있습니다.
Tim

22

추가 질문에 답변 :

typeid에 대한 다음 테스트 코드가 올바른 유형 이름을 출력하지 않습니다. 뭐가 문제 야?

문제가 없습니다. 보이는 것은 유형 이름의 문자열 표현입니다. 표준 C ++은 컴파일러가 클래스의 정확한 이름을 내도록 강요하지 않으며 적합한 것을 결정하는 것은 구현 자 (컴파일러 공급 업체)에 달려 있습니다. 요컨대, 이름은 컴파일러에 달려 있습니다.


이들은 두 가지 다른 도구입니다. typeof식의 유형을 반환하지만 표준이 아닙니다. C ++ 0x에는 decltypeAFAIK와 동일한 작업을 수행하는 것이 있습니다.

decltype(0xdeedbeef) number = 0; // number is of type int!
decltype(someArray[0]) element = someArray[0];

반면 typeid다형성 유형과 함께 사용됩니다. 예를 들어, 다음을 cat유도 한다고 가정 해 봅시다 animal.

animal* a = new cat; // animal has to have at least one virtual function
...
if( typeid(*a) == typeid(cat) )
{
    // the object is of type cat! but the pointer is base pointer.
}

감사합니다, 아라크! 방금 새로운 질문으로 게시물을 업데이트했습니다. 가능하면 살펴보세요.
Tim

4

typeid는 요청시 런타임시 데이터 유형을 제공합니다. Typedef는 그 이후에 명시된대로 새 유형을 정의하는 컴파일 시간 구성입니다. C ++에는 typeof가 없습니다 (출력 주석으로 표시됨).

std::cout << typeid(t).name() << std::endl;  // i
std::cout << typeid(person).name() << std::endl;   // 6Person
std::cout << typeid(employee).name() << std::endl; // 8Employee
std::cout << typeid(ptr).name() << std::endl;      // P6Person
std::cout << typeid(*ptr).name() << std::endl;     //8Employee

3

Boost demangle을 사용하여 멋진 이름을 얻을 수 있습니다.

#include <boost/units/detail/utility.hpp>

그리고 같은

To_main_msg_evt ev("Failed to initialize cards in " + boost::units::detail::demangle(typeid(*_IO_card.get()).name()) + ".\n", true, this);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.