Wie erhalte ich den Typ einer Variablen?

130

Wie findet man in C ++ den Typ einer Variablen?

0x499602D2
quelle
5
Mögliches Duplikat von stackoverflow.com/questions/81870/print-variable-type-in-c
theharshest
7
cout << typeid (variable) .name () << endl;
SRN
2
Verwenden Sie die Suche oder Google :) stackoverflow.com/questions/81870/print-variable-type-in-c Theharshest ist schnell: D
Kariboo
13
@ Kariboo, ich habe Google verwendet und es hat mich hierher geschickt.
Michael Warner
Diese Frage ist so wie sie ist sehr unklar, und selbst nachdem man die verschiedenen Antworten gesehen hat; Es ist keineswegs klar, dass die Frage die akzeptierte Antwort sucht.
Antti Haapala

Antworten:

154

Sie können den Operator typeid verwenden :

#include <typeinfo>
...
cout << typeid(variable).name() << endl;
Rich O'Kelly
quelle
14
@David - Bedeutet also iGanzzahl auf Ihrem Compiler. Die zurückgegebenen Namen werden vom Standard nicht angegeben.
Bo Persson
11
Wenn ich es für den Vektor <int> verwende, wird St6vectorIiSaIiEE zurückgegeben. WTF?
Boyan Kushlev
2
@ BobbyBrown du bist nicht allein !! google.co.uk/webhp#safe=off&q=St6vectorIiSaIiEE
Rich O'Kelly
4
Die von zurückgegebenen Namen typeidsind sehr abgekürzt, compilerspezifisch und nicht für den menschlichen Verzehr bestimmt. Sie können sie "entwirren" (das ist der eigentliche Begriff!), Entweder im Code mit so etwas wie gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html , mit Befehlszeilenprogrammen wie c++filtoder mit verschiedenen Online-Demanglern wie demangler.com .
Cincodenada
33

Für statische Zusicherungen wurde C ++ 11 eingeführt, decltypewas in bestimmten Szenarien sehr nützlich ist.

Nae
quelle
12

Wenn Sie eine Variable haben

int k;

Sie können seinen Typ mit erhalten

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

Siehe den folgenden Thread zu SO: Ähnliche Frage

Amit
quelle
9

Der Hauptunterschied zwischen C ++ und Javascript besteht darin, dass C ++ eine statisch typisierte Sprache ist, während Javascript dynamisch ist.

In dynamisch typisierten Sprachen kann eine Variable alles enthalten, und ihr Typ wird durch den Wert angegeben, den sie von Moment zu Moment enthält. In statisch typisierten Sprachen wird der Typ einer Variablen deklariert und kann nicht geändert werden.

Es kann eine dynamische Dispatch- und Objektzusammensetzung und -untertypisierung (Vererbung und virtuelle Funktionen) sowie eine statische Dispatching- und Supertypisierung (über das Vorlagen-CRTP) geben, aber in jedem Fall muss der Typ der Variablen dem Compiler bekannt sein.

Wenn Sie in der Lage sind, nicht zu wissen, was es ist oder sein könnte, liegt dies daran, dass Sie etwas entworfen haben, da die Sprache ein dynamisches Typsystem hat.

Wenn dies der Fall ist, sollten Sie Ihr Design besser überdenken, da es in ein Land geht, das für die Sprache, die Sie verwenden, nicht natürlich ist (meistens wie auf einer Autobahn mit einer Raupe oder im Wasser mit einem Auto).

Emilio Garavaglia
quelle
Wenn sich in C ++ die Dynamik ändert, dann denke ich, wäre es großartig und typeof und parseInt, parseFloat-Funktionen werden ebenfalls nützlich sein, aber ich weiß nicht, warum C ++ - Hersteller es zum Beispiel zu schwierig machen! wer sagt, dass es gut ist, cout << "String" zu schreiben
Waqas Tahir
Entschlossenheit ist am besten !!!! #include <sstream> string str ("1912"); int strtointval; stringstream (str) >> strtointval;
Waqas Tahir
@ Waqas Äh, was? Die Leute, die sagen, dass es am besten ist, sind die Leute, die die Sprache definieren, und IMO haben sie so ziemlich das letzte Wort, wenn es darum geht - zum Beispiel gute Codierungspraktiken. Könnten Sie diesen Kommentar umformulieren, damit er sinnvoller ist?
Fund Monica Klage
Ich bin völlig anderer Meinung. Java, C #, PHP, Perl, Python usw. wurden in C und C ++ entwickelt und sind keine Raupen. (Wenn Sie eine Datenbankanwendung erstellen, um Variablentabellen aus 'unbekannten' Datenbanken zu öffnen, müssen Sie den Feldtyp auf 'sehr' dymanische Weise in das Variablenschema und umgekehrt steuern;))
TomeeNS
@TomeeNS: Nein. Sie sind geschrieben in C und C ++, nicht ausgelegt . Sie sind so konzipiert, dass sie ihre Arbeit erledigen. Sie haben einen dynamischen Typ, auch wenn C und C ++ selbst dies nicht tun. Das ist nichts Seltsames daran.
Emilio Garavaglia
8

Normalerweise ist es die falsche Frage, den Typ einer Variablen in C ++ zu finden. Es ist etwas, das Sie aus prozeduralen Sprachen wie C oder Pascal mitnehmen.

Wenn Sie je nach Typ unterschiedliche Verhaltensweisen codieren möchten, versuchen Sie, z. B. Funktionsüberladung und Objektvererbung kennenzulernen . Dies ist an Ihrem ersten Tag in C ++ nicht sofort sinnvoll, aber bleiben Sie dabei.

Pontus Gagge
quelle
Nehmen wir an, Sie haben ein Klassenobjekt und ein Unterklassenbuch. Stellen Sie sich nun vor, Sie haben eine Box, in der viele Objekte gespeichert werden können, aber aus irgendeinem Grund möchten Sie alle darin enthaltenen Bücher auflisten. Das Überprüfen des Typs ist viel sauberer, dann muss eine Methode "Typ" zu Object hinzugefügt und dann in Buch überschrieben werden, um so etwas wie "Buch" zurückzugeben
Paulo Cesar
Wie bei jeder Regel gibt es Ausnahmen (daher meine "normalerweise"!), Und Container erhöhen tendenziell die Komplexität der Typentheorie. Ich habe Container mit polymorphen Objekten noch nie überfordert… in den meisten Fällen reichen einheitliche Containertypen mit Vorlagen aus und sind viel sauberer.
Pontus Gagge
Verwenden Sie keine Vorlagen?
Bryan Grace
6

Ich glaube, ich habe einen gültigen Anwendungsfall für die Verwendung von typeid (), genauso wie es für die Verwendung von sizeof () gültig ist. Für eine Vorlagenfunktion muss der Code basierend auf der Vorlagenvariablen als Sonderfall verwendet werden, damit ich maximale Funktionalität und Flexibilität bieten kann.

Es ist viel kompakter und wartbarer als die Verwendung von Polymorphismus, eine Instanz der Funktion für jeden unterstützten Typ zu erstellen. Selbst in diesem Fall könnte ich diesen Trick verwenden, um den Hauptteil der Funktion nur einmal zu schreiben:

Da der Code Vorlagen verwendet, sollte die folgende switch-Anweisung statisch in nur einen Codeblock aufgelöst werden, um alle falschen Fälle, AFAIK, zu optimieren.

Betrachten Sie dieses Beispiel, in dem wir möglicherweise eine Konvertierung durchführen müssen, wenn T ein Typ gegen einen anderen ist. Ich verwende es für die Klassenspezialisierung, um auf Hardware zuzugreifen, bei der die Hardware entweder den Typ myClassA oder myClassB verwendet. Bei einer Nichtübereinstimmung muss ich Zeit damit verbringen, die Daten zu konvertieren.

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
}
Dan Truong
quelle
1
TypeId: Ich konnte typeid () auf Arduino nicht verwenden. Außerdem ist typeid () eine Laufzeitprüfung , keine Kompilierungszeit, sodass sie nicht zum Generieren von optimiertem Code verwendet werden kann.
Dan Truong
1
Ja, nein, das macht nicht das, was du gedacht hast. typeidkann per Definition einfach keine statische Überprüfung zur Kompilierungszeit sein, daher erleichtert dies keine Optimierung. For a template function, I need to special case the code based on the template variableRichtig, was Sie also wirklich wollen, ist statischer Polymorphismus über das CRTP-Idiom. Genau das erreicht man.
underscore_d
4

Ich bin mir nicht sicher, ob meine Antwort helfen würde.

Die kurze Antwort lautet: Sie müssen / möchten den Typ einer Variablen nicht wirklich kennen, um sie verwenden zu können.

Wenn Sie einer statischen Variablen einen Typ zuweisen müssen, können Sie einfach auto verwenden.

In einem komplexeren Fall, in dem Sie "auto" in einer Klasse oder Struktur verwenden möchten, würde ich vorschlagen, eine Vorlage mit decltype zu verwenden.

Angenommen, Sie verwenden die Bibliothek eines anderen Benutzers und sie hat eine Variable namens "unknown_var". Sie möchten sie in einen Vektor oder eine Struktur einfügen. Sie können dies vollständig tun:

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

Hoffe das hilft.

EDIT: Zum guten Teil ist hier der komplexeste Fall, den ich mir vorstellen kann: eine globale Variable unbekannten Typs. In diesem Fall benötigen Sie c ++ 14 und eine Vorlagenvariable.

Etwas wie das:

template<typename T> vector<T> global_var;

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

Es ist immer noch etwas langweilig, aber es ist so nah wie möglich an typenlosen Sprachen. Stellen Sie einfach sicher, dass Sie immer die Vorlagenspezifikation dort einfügen, wenn Sie auf eine Vorlagenvariable verweisen.

Gohongyi
quelle
2
#include <typeinfo>

...
string s = typeid(YourClass).name()
rad
quelle
0

Wenn Sie einen Vergleich zwischen einer Klasse und einem bekannten Typ durchführen müssen, zum Beispiel:

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

Sie können diese Vergleichszeile verwenden:

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

typeidHiermit wird überprüft, ob der Name den Zeichenfolgentyp enthält ( der Name der Typ-ID enthält andere entstellte Daten, daher ist es am besten, eine s1.find(s2)anstelle von auszuführen ==).

jackw11111
quelle
-1

Sie können definitiv festlegen, typeid(x).name()wo x der Variablenname ist. Es gibt tatsächlich einen const char-Zeiger auf den Datentyp zurück. Schauen Sie sich nun den folgenden Code an.

#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;
}

Beachten Sie, wie erstens und zweitens beide funktionieren.

Pikachu
quelle
Das Erkennen des Typs am ersten Zeichen ist eine sehr schlechte Idee.
Dmitry Kuzminov
Könnten Sie bitte genauer Dmitry sein? Ich habe Ihren Standpunkt hier nicht verstanden.
Pikachu
Dies kann nur auf verkürzt werden std::cout << "I'm a variable of type " << typeid(n).name(). (umformuliert, um ein / ein Artefakt zu verhindern, aber das kann mit einer anderen Prüfung behoben werden). Selbst dann, wenn Sie unbedingt einen Vergleich wünschen, ist es viel bessertypeid(n) == typeid(int)
Zoe