typeid în C++

Dă informații despre tipul unei expresii la rulare; pentru clase cu funcții virtuale arată tipul real al obiectului.

Sintaxă
#include <typeinfo>
typeid(tip)
typeid(expresie)   // returnează const std::type_info&

Ce face typeid

typeid returnează un obiect std::type_info (din <typeinfo>) care descrie un tip. Două type_info pot fi comparate cu ==, iar .name() dă un nume al tipului.

Partea utilă: pentru o referință la o clasă cu funcții virtuale (polimorfică), typeid dă tipul real al obiectului de la rulare, nu tipul declarat. Pentru restul tipurilor, rezultatul se știe deja la compilare.

Textul returnat de .name() nu este standard: GCC și clang dau nume „codificate” (i pentru int, 5Caine pentru clasa Caine), iar Visual C++ dă nume ușor de citit. Rezultatele de mai jos sunt de la clang.

Exemple

Exemplul 1: Compararea tipurilor

#include <print>
#include <typeinfo>

int main() {
    int nota = 10;
    double media = 9.5;
    std::println("nota este int: {}", typeid(nota) == typeid(int));
    std::println("media este int: {}", typeid(media) == typeid(int));
    std::println("Nume (clang): {} și {}", typeid(nota).name(), typeid(media).name());
}

Rezultat

nota este int: true
media este int: false
Nume (clang): i și d

Exemplul 2: Tipul real al unui obiect polimorfic

Referința este de tip Animal&, dar obiectul este un Caine; pentru că Animal are o funcție virtuală, typeid vede tipul real.

#include <print>
#include <typeinfo>

struct Animal { virtual ~Animal() = default; };
struct Caine : Animal {};
struct Pisica : Animal {};

void identifica(const Animal& a) {
    if (typeid(a) == typeid(Caine)) {
        std::println("Este un câine ({})", typeid(a).name());
    } else if (typeid(a) == typeid(Pisica)) {
        std::println("Este o pisică ({})", typeid(a).name());
    }
}

int main() {
    Caine rex;
    Pisica tom;
    identifica(rex);
    identifica(tom);
}

Rezultat

Este un câine (5Caine)
Este o pisică (6Pisica)

Greșeli frecvente

  • Afișezi typeid(x).name() utilizatorului sau salvezi numele în fișiere. Textul diferă de la un compilator la altul; folosește-l doar pentru depanare.
  • Folosești typeid pe o clasă fără funcții virtuale și te aștepți la tipul real. Fără virtual, se vede doar tipul declarat al referinței.

Comenzi înrudite

  • static_cast, dynamic_cast, const_cast, reinterpret_cast: Cele patru conversii explicite: static_cast (obișnuite), dynamic_cast (clase), const_cast (const) și reinterpret_cast (biți).
  • virtual: Marchează o metodă care poate fi suprascrisă în clasele derivate; apelul printr-un pointer sau o referință la bază alege varianta tipului real.
  • decltype: Dă tipul exact al unei expresii, fără să o evalueze; util pentru a declara variabile „de același tip ca”.