2009-12-31 14 views
102

Mi chiedo quale sia la differenza tra typeid e typeof in C++. Ecco quello che so:'typeid' contro 'typeof' in C++

  • typeid è menzionato nella documentazione per type_info che è definito nel C++ file di intestazione typeinfo.

  • typeof è definito nell'estensione GCC per C e nella libreria C++ Boost.

Inoltre, qui è prova di codice di prova che ho creato in cui ho scoperto che typeid non restituisce quello che mi aspettavo. Perché?

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) 
} 

uscita:

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

In che modo pensi che il codice non stampa i nomi dei tipi giusti? Mi sembra buono La stringa effettiva restituita da 'name()' è definita dall'implementazione. Non deve essere un nome identificativo C++ valido, solo * qualcosa * che identifica univocamente il tipo. Sembra che la tua implementazione utilizzi lo schema generale di manipolazione dei nomi del compilatore. –

+0

Grazie Rob! Mi aspettavo che fossero esattamente identici ai nomi dei tipi che ho visto in en.wikipedia.org/wiki/Typeid. Cosa può fare la manipolazione del nome qui? – Tim

risposta

139

linguaggio C++ non ha alcuna cosa come typeof. Devi guardare un'estensione specifica per il compilatore. Se si sta parlando di GCC typeof, una caratteristica simile è presente in C++ 11 tramite la parola chiave decltype. Ancora una volta, C++ non ha tale parola chiave typeof.

typeid è un operatore di linguaggio C++ che restituisce informazioni di identificazione del tipo in fase di esecuzione. In pratica, restituisce un oggetto type_info, che è equivalente all'uguaglianza con altri oggetti type_info.

nota, che la proprietà unica definita del type_info oggetto restituito contiene è suo essere Uguaglianza e non-uguaglianza comparabile, ossia type_info oggetti che descrivono tipi diversi devono confrontare non uguali, mentre type_info oggetti che descrive lo stesso tipo devono confronta uguale. Tutto il resto è definito dall'implementazione. I metodi che restituiscono vari "nomi" non sono garantiti per restituire qualcosa di leggibile dall'uomo e persino non garantito restituire nulla.

Si noti inoltre, che la suddetta probabilmente implica (anche se lo standard non sembra accennare esplicitamente) che le applicazioni consecutive di typeid allo stesso tipo potrebbero restituire diversi type_info oggetti (che, naturalmente, devono ancora confrontare uguale).

+0

Grazie, AndreyT! Ho appena aggiornato il post con alcune nuove domande. Si prega di dare un'occhiata se possibile. – Tim

+0

non ha bisogno di un aggiornamento poiché C++ 11 ha 'decltype'? Non sono sicuro di quale sia la politica generale, ma dato che la domanda è codificata 'C++' mi aspetto che faccia riferimento all'ultimo standard. Ritornare alla domanda come 'C++ 03' sarebbe anche un'opzione imho. Personalmente a volte mi confondo, dato che devo usare preC++ 11 al lavoro e talvolta non sono sicuro di cosa sia vero "pre11" o "post11". – user463035818

+0

FYI, 'decltype' non sostituisce' typeof'. 'typeof' funziona anche sui tipi mentre' decltype' no. Ad esempio, 'typeof (int)' è 'int' mentre' decltype (int) 'è un errore. – Shahbaz

34

La differenza principale tra i due è il seguente

  • typeof è un costrutto tempo di compilazione e ritorna il tipo definito in compila il tempo
  • typeid è un costrutto runtime e quindi fornisce informazioni sul tipo di runtime del valore.

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

typeid Rfeerence: http://en.wikipedia.org/wiki/Typeid

+0

Grazie, JaredPar! Ho alcune nuove domande nel post aggiornato dopo aver letto le tue risposte. Come se fosse anche vero che i loro ritorni sono usati per scopi diversi: il ritorno di typeof è usato come parola chiave type che può definire variabile, ma il ritorno di typeid non può? – Tim

23

typeid può operare in fase di esecuzione, e restituire un oggetto che descrive il tipo runtime dell'oggetto, che deve essere un puntatore a un oggetto di una classe con metodi virtuali in modo che RTTI (run-time type information) sia memorizzato nella classe. Può anche fornire il tipo di tempo di compilazione di un'espressione o un nome di tipo, se non viene fornito un puntatore a una classe con informazioni sul tipo di esecuzione.

typeof è un'estensione GNU e fornisce il tipo di qualsiasi espressione in fase di compilazione. Ciò può essere utile, ad esempio, nel dichiarare variabili temporanee in macro che possono essere utilizzate su più tipi. In C++, di solito si utilizza templates.

+4

Per quanto ne so, 'typeid' accetterà qualsiasi espressione, non solo quelle che valutano gli oggetti con metodi virtuali. Inoltre, 'typeid' accetterà un tipo * nome *, non solo un'espressione. Puoi dire 'typeid (5)' o 'typeid (std :: string)' se vuoi. –

+1

Ho chiarito la mia risposta per chiarire questo punto; 'typeid' * can * restituisce le informazioni sul tipo di runtime se disponibili, ma fornirà informazioni sul tipo di tempo di compilazione per qualsiasi altra cosa. –

+0

Grazie, Brian e Rob!Ho alcune nuove domande nel post aggiornato dopo aver letto le tue risposte. – Tim

19

Rispondendo alla domanda aggiuntiva:

mia seguente codice di prova per typeid fa non uscita il nome del tipo corretto. cosa c'è che non va?

Non c'è niente di sbagliato. Quello che vedi è la rappresentazione in stringa del nome del tipo. Lo standard C++ non obbliga i compilatori ad emettere il nome esatto della classe, spetta solo all'implementatore (produttore del compilatore) decidere quale sia il caso. In breve, i nomi sono validi per il compilatore.


Questi sono due strumenti diversi.typeof restituisce il tipo di un'espressione, ma non è standard. In C++ 0x c'è qualcosa chiamato decltype che fa lo stesso lavoro AFAIK.

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

Mentre typeid viene utilizzato con tipi polimorfi. Ad esempio, consente di dire che cat deriva 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. 
} 
+0

Grazie, Arak! Ho appena aggiornato il post con alcune nuove domande. Si prega di dare un'occhiata se possibile. – Tim

2

È possibile utilizzare Boost demangle per realizzare un bel nome cercando:

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

e qualcosa come

To_main_msg_evt ev("Failed to initialize cards in " + boost::units::detail::demangle(typeid(*_IO_card.get()).name()) + ".\n", true, this); 
4

typeid fornisce il tipo di dati in fase di runtime, quando ha chiesto. Typedef è un costrutto di tempo di compilazione che definisce un nuovo tipo come indicato successivamente. Non v'è alcun typeof in C++ uscita appare come (indicato come commenti iscritti):

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