typeid 用於獲取表達式或類型的類型信息,返回 const type_info&。類型信息包含:基本型別的名稱、類型別的類關係、成員、繼承體系等。
typeid(類型名) // 如 typeid(int), typeid(MyClass) typeid(表達式) // 如 typeid(x), typeid(*ptr), typeid(a+b)
類似 sizeof,但必須帶括號。需包含 <typeinfo>。
| 函數 | 功能 | 標準規定 |
|---|---|---|
name() | 返回類型名稱字串 | 實現定義(MSVC: "class Base", GCC: "4Base") |
raw_name() | 返回修飾名 | MSVC 專有 |
hash_code() | 返回類型雜湊值 | C++11 標準 |
before() | 類型順序比較 | 實現定義,無語義保證 |
operator==/!= | 類型相等/不等判斷 | 標準要求 |
#include <iostream>
#include <typeinfo>
using namespace std;
class Base {};
struct STU {};
int main() {
int n = 100;
const type_info& nInfo = typeid(n);
cout << nInfo.name() << " | " << nInfo.raw_name() << " | " << nInfo.hash_code() << endl;
const type_info& dInfo = typeid(25.65);
cout << dInfo.name() << " | " << dInfo.raw_name() << " | " << dInfo.hash_code() << endl;
Base obj;
cout << typeid(obj).name() << " | " << typeid(obj).hash_code() << endl;
cout << typeid(Base).name() << " | " << typeid(Base).hash_code() << endl;
cout << typeid(STU).name() << " | " << typeid(STU).hash_code() << endl;
cout << typeid(char).name() << " | " << typeid(char).hash_code() << endl;
cout << typeid(20 * 45 / 4.5).name() << " | " << typeid(20 * 45 / 4.5).hash_code() << endl;
}
int | .H | 529034928 double | .N | 667332678 class Base | .?AVBase@@ | 1035034353 class Base | .?AVBase@@ | 1035034353 struct STU | .?AUSTU@@ | 734635517 char | .D | 4140304029 double | .N | 667332678
i | (null) | 123456 d | (null) | 789012 4Base | (null) | 345678 4Base | (null) | 345678 4STU | (null) | 901234 c | (null) | 567890 d | (null) | 789012
關鍵結論:name() 返回值高度依賴實現,不可跨平台依賴具體字串格式。
char* str; int a=2, b=10; float f; typeid(int) == typeid(int) // true typeid(int) == typeid(char) // false typeid(str) == typeid(char*) // true typeid(a) == typeid(b) // true (同類型) typeid(a/b) == typeid(int) // true (整數除法結果為 int)
同一類型在程式中僅有一個 type_info 物件,所有 typeid 返回其引用。
class Base {}; class Derived : public Base {};
Base obj1, *p1; Derived obj2, *p2 = new Derived;
p1 = p2; // 基類指針指向派生物件
typeid(obj1) == typeid(p1) // false (Base vs Base*)
typeid(obj1) == typeid(*p1) // true (Base vs Base)
typeid(&obj1) == typeid(p1) // true (Base* vs Base*)
typeid(obj1) == typeid(obj2) // false (Base vs Derived)
typeid(obj1) == typeid(Base) // true
typeid(*p1) == typeid(Base) // true // 關鍵:靜態類型為 Base
typeid(p1) == typeid(Base*) // true
typeid(p1) == typeid(Derived*) // false
重要:typeid(*p1) 取決於指針靜態類型(此處為 Base*),而非動態類型。要獲取動態類型需配合 virtual 函數(RTTI 完整機制見後續章節)。
class type_info {
public:
virtual ~type_info();
bool operator==(const type_info&) const;
bool operator!=(const type_info&) const;
bool before(const type_info&) const;
const char* name() const;
const char* raw_name() const; // MSVC 擴展
private:
void* _m_data;
char _m_d_name[1];
type_info(const type_info&); // 禁止拷貝
type_info& operator=(const type_info&); // 禁止賦值
};
private:只能由編譯器內部建構typeid 的類型生成 type_info,含虛函數的類除外(必須生成)typeid 是 C++ RTTI 的入口,提供基礎類型查詢能力。但跨平台名稱不一致、功能極弱、僅支援靜態類型查詢(除非配合虛函數)。實務中主要用於 typeid(a) == typeid(b) 類型比對,複雜反射需求建議使用第三方庫或編譯期元程式技術。