In C ++, come si trova il tipo di una variabile?
In C ++, come si trova il tipo di una variabile?
Risposte:
Puoi usare l'operatore typeid :
#include <typeinfo>
...
cout << typeid(variable).name() << endl;
i
significa numero intero sul tuo compilatore. I nomi restituiti non sono specificati dallo standard.
typeid
sono molto abbreviati, specifici del compilatore e non destinati al consumo umano. Puoi "smangiarli" (questo è il termine effettivo!), Sia in codice con qualcosa come gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html , con utilità a riga di comando come c++filt
, o con uno qualsiasi dei vari demanglers online come demangler.com .
Se hai una variabile
int k;
Puoi ottenere il suo tipo usando
cout << typeid(k).name() << endl;
Vedi il seguente thread su SO: Domanda simile
La principale differenza tra C ++ e Javascript è che C ++ è un linguaggio di tipo statico, mentre javascript è dinamico.
Nei linguaggi tipizzati dinamici una variabile può contenere qualsiasi cosa, e il suo tipo è dato dal valore che detiene, momento per momento. Nei linguaggi di tipo statico il tipo di una variabile è dichiarato e non può cambiare.
Possono esserci invio dinamico e composizione di oggetti e sottotipizzazione (ereditarietà e funzioni virtuali), invio statico e supertyping (tramite template CRTP), ma in ogni caso il tipo di variabile deve essere noto al compilatore.
Se sei nella posizione di non sapere cosa sia o potrebbe essere, è perché hai progettato qualcosa poiché il linguaggio ha un sistema di tipi dinamico.
Se questo è il caso, è meglio che tu ripensi il tuo progetto, poiché sta andando in una terra non naturale per la lingua che stai usando (più come andare in autostrada con un bruco, o in acqua con una macchina)
Di solito, voler trovare il tipo di una variabile in C ++ è la domanda sbagliata. Tende ad essere qualcosa che ti porti dietro da linguaggi procedurali come ad esempio C o Pascal.
Se si desidera codificare comportamenti diversi a seconda del tipo, provare a conoscere ad esempio il sovraccarico delle funzioni e l' ereditarietà degli oggetti . Questo non avrà immediatamente senso nel tuo primo giorno di C ++, ma continua a farlo.
Credo di avere un caso d'uso valido per l'utilizzo di typeid (), allo stesso modo in cui è valido usare sizeof (). Per una funzione template, ho bisogno di un caso speciale del codice basato sulla variabile template, in modo da offrire la massima funzionalità e flessibilità.
È molto più compatto e gestibile rispetto all'utilizzo del polimorfismo, per creare un'istanza della funzione per ogni tipo supportato. Anche in quel caso potrei usare questo trucco per scrivere il corpo della funzione solo una volta:
Si noti che poiché il codice utilizza modelli, l'istruzione switch seguente dovrebbe risolversi staticamente in un solo blocco di codice, ottimizzando tutti i casi falsi, AFAIK.
Considera questo esempio, in cui potrebbe essere necessario gestire una conversione se T è un tipo rispetto a un altro. Lo uso per la specializzazione di classe per accedere all'hardware in cui l'hardware utilizzerà il tipo myClassA o myClassB. In caso di mancata corrispondenza, è necessario dedicare tempo alla conversione dei dati.
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
}
typeid
semplicemente non può essere un controllo statico in fase di compilazione - per definizione - quindi questo non facilita alcuna ottimizzazione. For a template function, I need to special case the code based on the template variable
Bene, quindi quello che vuoi veramente è il polimorfismo statico tramite l'idioma CRTP. Questo è esattamente ciò che si ottiene.
Non sono sicuro che la mia risposta aiuterebbe.
La risposta breve è che non hai davvero bisogno / vuoi sapere il tipo di variabile per usarla.
Se hai bisogno di dare un tipo a una variabile statica, puoi semplicemente usare auto.
Nel caso più sofisticato in cui si desidera utilizzare "auto" in una classe o in una struttura, suggerirei di utilizzare template con decltype.
Ad esempio, supponiamo che tu stia usando la libreria di qualcun altro e che abbia una variabile chiamata "unknown_var" e vorresti metterla in un vettore o in una struttura, puoi farlo totalmente:
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
Spero che questo ti aiuti.
EDIT: Per buona misura, ecco il caso più complesso a cui posso pensare: avere una variabile globale di tipo sconosciuto. In questo caso avresti bisogno di c ++ 14 e di una variabile template.
Qualcosa come questo:
template<typename T> vector<T> global_var;
void random_func (auto unknown_var) {
global_var<decltype(unknown_var)>.push_back(unknown_var);
}
È ancora un po 'noioso ma è il più vicino possibile alle lingue senza tipizzazione. Assicurati solo ogni volta che fai riferimento alla variabile del modello, inserisci sempre la specifica del modello lì.
Se devi fare un confronto tra una classe e un tipo noto, ad esempio:
class Example{};
...
Example eg = Example();
Puoi usare questa riga di confronto:
bool isType = string( typeid(eg).name() ).find("Example") != string::npos;
che controlla che il typeid
nome contenga il tipo stringa (il nome typeid ha altri dati alterati, quindi è meglio fare un s1.find(s2)
invece di ==
).
Puoi sicuramente cercare typeid(x).name()
dove x è il nome della variabile. Restituisce effettivamente un puntatore a un carattere const al tipo di dati. Ora guarda il seguente codice.
#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;
}
Notare come il primo e il secondo funzionano entrambi.
std::cout << "I'm a variable of type " << typeid(n).name()
. (riformulato per evitare artefatti, ma può essere risolto con un altro controllo). Anche allora, se vuoi assolutamente un confronto, è molto meglio farlotypeid(n) == typeid(int)