Namensräume
Varianten
Aktionen

typeid Operator

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Fragt Informationen über einen Typ ab.

Wird verwendet, wenn der dynamische Typ eines polymorphen Objekts bekannt sein muss, und für die statische Typidentifizierung.

Inhalt

[bearbeiten] Syntax

typeid ( Typ ) (1)
typeid ( Ausdruck ) (2)

Der typeid-Ausdruck ist ein lvalue-Ausdruck, der auf ein Objekt mit statischer Speicherklasse verweist, und zwar auf die const-qualifizierte Version des polymorphen Typs std::type_info oder einen davon abgeleiteten Typ.

Wenn die Standardbibliotheksdefinition von std::type_info bei der Verwendung von typeid nicht sichtbar ist, ist das Programm schlecht geformt.

[bearbeiten] Erklärung

Wenn Typ oder der Typ von Ausdruck ein Klassentyp oder eine Referenz auf einen Klassentyp ist, dann darf dieser Klassentyp kein unvollständiger Typ sein.

1) Verweist auf ein std::type_info-Objekt, das Typ repräsentiert. Wenn Typ ein Referenztyp ist, verweist das Ergebnis auf ein std::type_info-Objekt, das die cv-unqualifizierte Version des referenzierten Typs repräsentiert.
2) Untersucht Ausdruck.
  • Wenn Ausdruck ein lvalue(bis C++11)glvalue(seit C++11) Ausdruck ist, der ein Objekt eines polymorphen Typs identifiziert (d. h. eine Klasse, die mindestens eine virtuelle Funktion deklariert oder erbt), wertet der typeid-Ausdruck den Ausdruck aus und verweist dann auf das std::type_info-Objekt, das den dynamischen Typ des Ausdrucks repräsentiert.
  • Andernfalls wertet typeid den Ausdruck nicht aus, und das von std::type_info identifizierte Objekt repräsentiert den statischen Typ des Ausdrucks. Lvalue-zu-rvalue-, Array-zu-Zeiger- oder Funktions-zu-Zeiger-Konvertierungen werden nicht durchgeführt.
  • Allerdings wird eine temporäre Materialisierung für prvalue-Argumente (formal) durchgeführt: Das Argument muss im Kontext, in dem der typeid-Ausdruck erscheint, zerstörbar sein.
(seit C++17)

Wenn Typ oder der Typ von Ausdruck cv-qualifiziert ist, verweist das Ergebnis von typeid auf ein std::type_info-Objekt, das den cv-unqualifizierten Typ repräsentiert (d. h. typeid(const T) == typeid(T)).

Wenn typeid auf ein Objekt während des Konstruktions- oder Zerstörungsprozesses angewendet wird (in einem Destruktor oder in einem Konstruktor, einschließlich der Initialisierungsliste oder Standard-Member-Initialisierer), dann repräsentiert das von diesem typeid referenzierte std::type_info-Objekt die Klasse, die gerade konstruiert oder zerstört wird, auch wenn es nicht die am weitesten abgeleitete Klasse ist.

  1. In anderen Kontexten führt die Auswertung eines solchen Ausdrucks zu undefiniertem Verhalten.

[bearbeiten] Anmerkungen

Wenn typeid auf einen Ausdruck vom polymorphen Typ angewendet wird, kann die Auswertung von typeid Laufzeitaufwand verursachen (ein virtueller Tabellen-Lookup); andernfalls wird der typeid-Ausdruck zur Kompilierzeit aufgelöst.

Es ist nicht spezifiziert, ob der Destruktor für das Objekt, auf das von typeid verwiesen wird, am Ende des Programms aufgerufen wird.

Es gibt keine Garantie, dass auf dasselbe std::type_info-Objekt von allen Auswertungen des typeid-Ausdrucks auf denselben Typ verwiesen wird, obwohl sie gleich verglichen würden, std::type_info::hash_code dieser type_info-Objekte identisch wäre, ebenso wie ihr std::type_index.

const std::type_info& ti1 = typeid(A);
const std::type_info& ti2 = typeid(A);
 
assert(&ti1 == &ti2); // not guaranteed
assert(ti1 == ti2); // guaranteed
assert(ti1.hash_code() == ti2.hash_code()); // guaranteed
assert(std::type_index(ti1) == std::type_index(ti2)); // guaranteed

[bearbeiten] Schlüsselwörter

typeid

[bearbeiten] Beispiel

Das Beispiel zeigt die Ausgabe einer der Implementierungen, bei der type_info::name vollständige Typnamen zurückgibt; filtern Sie mit c++filt -t, wenn Sie gcc oder ähnliches verwenden.

#include <iostream>
#include <string>
#include <typeinfo>
 
struct Base {}; // non-polymorphic
struct Derived : Base {};
 
struct Base2 { virtual void foo() {} }; // polymorphic
struct Derived2 : Base2 {};
 
int main()
{
    int myint = 50;
    std::string mystr = "string";
    double *mydoubleptr = nullptr;
 
    std::cout << "myint has type: " << typeid(myint).name() << '\n'
              << "mystr has type: " << typeid(mystr).name() << '\n'
              << "mydoubleptr has type: " << typeid(mydoubleptr).name() << '\n';
 
    // std::cout << myint is a glvalue expression of polymorphic type; it is evaluated
    const std::type_info& r1 = typeid(std::cout << myint); // side-effect: prints 50
    std::cout << '\n' << "std::cout<<myint has type : " << r1.name() << '\n';
 
    // std::printf() is not a glvalue expression of polymorphic type; NOT evaluated
    const std::type_info& r2 = typeid(std::printf("%d\n", myint));
    std::cout << "printf(\"%d\\n\",myint) has type : " << r2.name() << '\n';
 
    // Non-polymorphic lvalue is a static type
    Derived d1;
    Base& b1 = d1;
    std::cout << "reference to non-polymorphic base: " << typeid(b1).name() << '\n';
 
    Derived2 d2;
    Base2& b2 = d2;
    std::cout << "reference to polymorphic base: " << typeid(b2).name() << '\n';
 
    try
    {
        // dereferencing a null pointer: okay for a non-polymorphic expression
        std::cout << "mydoubleptr points to " << typeid(*mydoubleptr).name() << '\n'; 
        // dereferencing a null pointer: not okay for a polymorphic lvalue
        Derived2* bad_ptr = nullptr;
        std::cout << "bad_ptr points to... ";
        std::cout << typeid(*bad_ptr).name() << '\n';
    }
    catch (const std::bad_typeid& e)
    {
        std::cout << " caught " << e.what() << '\n';
    }
}

Mögliche Ausgabe

======== output from Clang ========
myint has type: i
mystr has type: NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
mydoubleptr has type: Pd
50
std::cout<<myint has type : NSt3__113basic_ostreamIcNS_11char_traitsIcEEEE
printf("%d\n",myint) has type : i
reference to non-polymorphic base: 4Base
reference to polymorphic base: 8Derived2
mydoubleptr points to d
bad_ptr points to...  caught std::bad_typeid
 
======== output from MSVC ========
myint has type: int
mystr has type: class std::basic_string<char,struct std::char_traits<char>,⮠
class std::allocator<char> >
mydoubleptr has type: double * __ptr64
50
std::cout<<myint has type : class std::basic_ostream<char,struct std::char_traits<char> >
printf("%d\n",myint) has type : int
reference to non-polymorphic base: struct Base
reference to polymorphic base: struct Derived2
mydoubleptr points to double
bad_ptr points to...  caught Attempted a typeid of nullptr pointer!

[bearbeiten] Fehlerberichte

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 492 C++98 wenn typeid auf eine Referenz auf einen cv-qualifizierten Typ angewendet wird
repräsentierte das Ergebnis den referenzierten Typ
das Ergebnis repräsentiert den
cv-unqualifizierten referenzierten Typ
CWG 1416 C++98 die Formulierung bezüglich der obersten
cv-Qualifikation könnte fehlinterpretiert werden
verbesserte die Formulierung
CWG 1431 C++98 typeid durfte nur std::bad_typeid auslösen durfte auslösen
abgleichbare abgeleitete Klassen
CWG 1954 C++98 es war unklar, ob eine Dereferenzierung eines Nullzeigers
in Subausdrücken von Ausdruck überprüft werden kann
nur auf oberster Ebene überprüft

[bearbeiten] Siehe auch

enthält Informationen über bestimmte Typen, die Klasse, die vom typeid-Operator zurückgegeben wird
(Klasse) [bearbeiten]