변수 유형은 어떻게 얻습니까?


130

C ++에서 변수의 유형을 어떻게 찾습니까?



7
cout << typeid (변수) .name () << endl;
SRN 2012

2
검색 또는 구글 사용 :) stackoverflow.com/questions/81870/print-variable-type-in-c Theharshest is fast : D
Kariboo

14
@Kariboo, 나는 Google을 사용했고 나를 여기로 보냈습니다.
Michael Warner

이 질문은 현재로서는 매우 불분명하며 다양한 답변을 본 후에도 불분명합니다. 질문이 받아 들여진 답을 찾고 있다는 것은 결코 분명하지 않습니다.
Antti Haapala

답변:


158

typeid 연산자를 사용할 수 있습니다 .

#include <typeinfo>
...
cout << typeid(variable).name() << endl;

15
@David-따라서 i컴파일러에서 정수를 의미합니다. 반환 된 이름은 표준에 의해 지정되지 않습니다.
Bo Persson 2012

11
vector <int>에서 사용하면 St6vectorIiSaIiEE를 반환합니다. WTF?
Boyan Kushlev

2
@BobbyBrown 당신은 혼자가 아닙니다! google.co.uk/webhp#safe=off&q=St6vectorIiSaIiEE
Rich O'Kelly

5
에서 반환 된 이름 typeid은 매우 축약되고 컴파일러에 따라 다르며 사람이 사용할 수 없습니다. gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html 과 같은 코드에서 ,와 같은 명령 줄 유틸리티 c++filt를 사용하거나 다양한 온라인 demangler를 사용하여 코드를 "demangle"할 수 있습니다 (실제 용어입니다!). demangler.com 과 같은 .
cincodenada

33

정적 어설 션의 경우 decltype특정 시나리오에서 매우 유용한 C ++ 11이 도입되었습니다 .


12

변수가있는 경우

int k;

사용하여 유형을 얻을 수 있습니다.

cout << typeid(k).name() << endl;

SO에 대한 다음 스레드를 참조하십시오. 비슷한 질문


9

C ++와 Javascript의 주요 차이점은 C ++는 정적 유형 언어이고 wile javascript는 동적이라는 것입니다.

동적 유형 언어에서 변수는 모든 것을 포함 할 수 있으며 그 유형은 순간적으로 보유한 값에 의해 제공됩니다. 정적 유형 언어에서는 변수 유형이 선언되며 변경할 수 없습니다.

동적 디스패치 및 객체 구성 및 하위 유형 (상속 및 가상 함수)과 정적 디스패치 및 수퍼 타이핑 (템플릿 CRTP를 통해)이있을 수 있지만, 어떤 경우에도 변수 유형은 컴파일러에 알려야합니다.

그것이 무엇인지, 무엇이 될 수 있는지 모르는 위치에 있다면, 언어가 동적 유형 시스템을 가지고 있기 때문에 무언가를 설계했기 때문입니다.

그럴 경우 디자인을 다시 생각하는 것이 더 낫다면, 사용하는 언어로 자연스럽지 않은 땅으로 들어가기 때문입니다 (가장 애벌레가있는 고속도로 나 자동차로 물속에 들어가는 것과 비슷 함).


C ++에 동적 변경이 있으면 훌륭하고 typeof 및 parseInt, parseFloat 함수도 유용 할 것이라고 생각하지만 C ++ 제작자가 왜 그것을 너무 어렵게 만드는지 모르겠습니다! 누가 쓰기 cout과 << "문자열"로 그것의 좋은 말한다
Waqas 타히르

결단력이 최고 !!!! #include <sstream> 문자열 str ( "1912"); int strtointval; stringstream (str) >> strtointval;
Waqas Tahir

@Waqas 어, 뭐? 그것이 가장 좋다고 말하는 사람들은 언어를 정의하는 사람들이고, IMO는 그것과 관련된 모든 것에 대해 거의 최종적으로 말하고 있습니다. 더 이해하기 쉽게 그 댓글을 바꿔 줄 수 있나요?
기금 모니카의 소송

나는 완전히 동의하지 않는다. Java, C #, PHP, Perl, Python 등은 C 및 C ++로 설계되었으며 애벌레가 아닙니다. ( '알 수없는'데이터베이스에서 변수 테이블을 열기 위해 데이터베이스 응용 프로그램을 만들 때 필드 유형을 가변 스키마로, 그
반대로

@TomeeNS : 아니요. 그들은 C 및 C ++ 로 작성 되었으며 . 작업을 수행하도록 설계되었으며 C와 C ++ 자체가 그렇지 않더라도 동적 유형이 있습니다. 그것은 이상하지 않습니다.
Emilio Garavaglia

8

일반적으로 C ++에서 변수 유형을 찾는 것은 잘못된 질문입니다. 예를 들어 C 또는 Pascal과 같은 절차 언어에서 수행하는 경향이 있습니다.

유형에 따라 다른 동작을 코딩하려면 함수 오버로딩객체 상속 에 대해 알아보십시오 . 이것은 C ++의 첫날에 즉각적인 의미가 없지만 계속 유지하십시오.


실제로는 Object 클래스와 Book 하위 클래스가 있다고 가정 해 보겠습니다. 이제 많은 개체를 저장할 수있는 상자가 있다고 가정 해 보겠습니다. 그러나 어떤 이유로 그 안에있는 모든 책을 나열하려고합니다. 유형을 선택하면 훨씬 청소기 다음 "책"처럼 반환에 책에 뭔가를을 객체로하는 방법 "유형"을 추가 한 다음 오버라이드 (override) 할 필요가있다
파울로 세자르

모든 규칙과 마찬가지로 예외가 있으며 (따라서 '보통'입니다!) 컨테이너는 유형 이론에 복잡성을 추가하는 경향이 있습니다. 나는 다형성 객체의 컨테이너를 너무 좋아 한 적이 없다. 대부분의 경우 템플릿 화 된 균일 한 컨테이너 유형으로 충분하고 훨씬 더 깔끔하다.
Pontus Gagge

템플릿을 사용하지 않습니까?
Bryan Grace

6

sizeof ()를 사용하는 것과 같은 방식으로 typeid () 사용에 대한 유효한 사용 사례가 있다고 생각합니다. 템플릿 함수의 경우 최대한의 기능과 유연성을 제공하기 위해 템플릿 변수를 기반으로하는 코드를 특수하게 처리해야합니다.

지원되는 각 유형에 대해 하나의 함수 인스턴스를 만드는 것은 다형성을 사용하는 것보다 훨씬 간결하고 유지 관리가 쉽습니다. 이 경우에도이 트릭을 사용하여 함수 본문을 한 번만 작성할 수 있습니다.

코드는 템플릿을 사용하기 때문에 아래의 switch 문은 하나의 코드 블록으로 정적으로 해석되어 모든 잘못된 경우 AFAIK를 최적화해야합니다.

T가 한 유형과 다른 유형 인 경우 변환을 처리해야 할 수있는이 예제를 고려하십시오. 하드웨어가 myClassA 또는 myClassB 유형을 사용하는 하드웨어에 액세스하기 위해 클래스 전문화에 사용합니다. 불일치시 데이터 변환에 시간을 투자해야합니다.

switch ((typeid(T)) {
  case typeid(myClassA):
    // handle that case
    break;
  case typeid(myClassB):
    // handle that case
    break;
  case typeid(uint32_t):
    // handle that case
    break;
  default:
    // handle that case
}

1
TypeId : Arduino에서 typeid ()를 사용할 수 없습니다. 또한 typeid ()는 컴파일 시간이 아닌 런타임 검사이므로 최적화 된 코드를 생성하는 데 사용할 수 없습니다.
댄의 Truong

1
그래, 아냐, 이건 당신이 생각했던대로되지 않아 typeid정의에 따라 정적 컴파일 시간 검사가 될 수 없으므로 최적화가 용이하지 않습니다. For a template function, I need to special case the code based on the template variable맞습니다. 정말로 원하는 것은 CRTP 관용구를 통한 정적 다형성입니다. 이것이 바로 그것이 달성 한 것입니다.
underscore_d

4

내 대답이 도움이 될지 모르겠습니다.

짧은 대답은 사용하기 위해 변수의 유형을 실제로 알 필요가 / 알고 싶지 않다는 것입니다.

정적 변수에 유형을 지정해야하는 경우 auto를 사용하면됩니다.

클래스 나 구조체에서 "auto"를 사용하려는보다 복잡한 경우에는 decltype과 함께 템플릿을 사용하는 것이 좋습니다.

예를 들어, 다른 사람의 라이브러리를 사용 중이고 "unknown_var"라는 변수가 있고 벡터 또는 구조체에 넣으려면 다음과 같이 할 수 있습니다.

template <typename T>
struct my_struct {
    int some_field;
    T my_data;
};
vector<decltype(unknown_var)> complex_vector;
vector<my_struct<decltype(unknown_var)> > simple_vector

도움이 되었기를 바랍니다.

편집 : 좋은 측정을 위해 여기에 내가 생각할 수있는 가장 복잡한 경우가 있습니다. 알 수없는 유형의 전역 변수가 있습니다. 이 경우 C ++ 14 및 템플릿 변수가 필요합니다.

이 같은:

template<typename T> vector<T> global_var;

void random_func (auto unknown_var) {
    global_var<decltype(unknown_var)>.push_back(unknown_var);
}

여전히 약간 지루하지만 유형없는 언어에 도달 할 수있는 한 가깝습니다. 템플릿 변수를 참조 할 때마다 항상 템플릿 사양을 거기에 넣으십시오.


2
#include <typeinfo>

...
string s = typeid(YourClass).name()

0

클래스와 알려진 유형을 비교해야하는 경우 예를 들면 다음과 같습니다.

class Example{};
...
Example eg = Example();

이 비교 라인을 사용할 수 있습니다.

bool isType = string( typeid(eg).name() ).find("Example") != string::npos;

typeid이름에 문자열 유형이 포함되어 있는지 확인합니다 (typeid 이름에는 다른 데이터가 손상되어 있으므로 대신를 수행하는 s1.find(s2)것이 가장 좋습니다 ==).


-2

typeid(x).name()x가 변수 이름 인 곳으로 확실히 갈 수 있습니다 . 실제로 데이터 유형에 대한 const char 포인터를 반환합니다. 이제 다음 코드를보십시오.

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n = 36;
    char c = 'A';
    double d = 1.2;
    if(*(typeid(n).name()) == 'i'){
        cout << "I am an Integer variable" << endl;
    }
    if(*((char *) typeid(d).name()) == 'd'){
        cout << "I am a Double variable" << endl;
    }
    if(*((char *) typeid(c).name()) == 'c'){
        cout << "I am a Char variable" << endl;
    }
    return 0;
}

첫 번째와 두 번째가 모두 작동하는지 확인하십시오.


첫 번째 문자로 유형을 인식하는 것은 매우 나쁜 생각입니다.
Dmitry Kuzminov

좀 더 구체적으로 말씀해 주시겠습니까? 나는 여기서 당신의 요지를 이해하지 못했습니다.
Pikachu

이것은 std::cout << "I'm a variable of type " << typeid(n).name(). (아티팩트를 방지하기 위해 변경되었지만 다른 검사로 수정할 수 있습니다). 그럼에도 불구하고 절대적으로 비교를 원하면 훨씬 더 낫습니다typeid(n) == typeid(int)
Zoe
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.