c++ typeid關(guān)鍵字的使用
typeid關(guān)鍵字
注意:typeid是操作符,不是函數(shù)。這點(diǎn)與sizeof類似)
運(yùn)行時(shí)獲知變量類型名稱,可以使用 typeid(變量).name()
需要注意不是所有編譯器都輸出”int”、”float”等之類的名稱,對(duì)于這類的編譯器可以這樣使用
int ia = 3; if(typeid(ia) == typeid(int)) { cout <<"int" <<endl; }
RTTI(Run-Time Type Identification)-運(yùn)行時(shí)類型識(shí)別
在揭開typeid神秘面紗之前,我們先來了解一下RTTI(Run-Time Type Identification,運(yùn)行時(shí)類型識(shí)別),它使程序能夠獲取由基指針或引用所指向的對(duì)象的實(shí)際派生類型,即允許“用指向基類的指針或引用來操作對(duì)象”的程序能夠獲取到“這些指針或引用所指對(duì)象”的實(shí)際派生類型。
在C++中,為了支持RTTI提供了兩個(gè)操作符:dynamic_cast和typeid
- dynamic_cast允許運(yùn)行時(shí)刻進(jìn)行類型轉(zhuǎn)換,從而使程序能夠在一個(gè)類層次結(jié)構(gòu)中安全地轉(zhuǎn)化類型,與之相對(duì)應(yīng)的還有一個(gè)非安全的轉(zhuǎn)換操作符static_cast,因?yàn)檫@不是本文的討論重點(diǎn),所以這里不再詳述,感興趣的可以自行查閱資料。
- typeid是C++的關(guān)鍵字之一,等同于sizeof這類的操作符。typeid操作符的返回結(jié)果是名為type_info的標(biāo)準(zhǔn)庫(kù)類型的對(duì)象的引用(在頭文件typeinfo中定義,稍后我們看一下vs和gcc庫(kù)里面的源碼),它的表達(dá)式有下圖兩種形式。
實(shí)現(xiàn)機(jī)制與使用技巧
type_info類對(duì)象類別判別
對(duì)象類別判別分析
如果表達(dá)式的類型是類類型且至少包含有一個(gè)虛函數(shù),則typeid操作符返回表達(dá)式的動(dòng)態(tài)類型,需要在運(yùn)行時(shí)計(jì)算;
否則,typeid操作符返回表達(dá)式的靜態(tài)類型,在編譯時(shí)就可以計(jì)算。
ISO C++標(biāo)準(zhǔn)并沒有確切定義type_info,它的確切定義編譯器相關(guān)的,但是標(biāo)準(zhǔn)卻規(guī)定了其實(shí)現(xiàn)必需提供如下四種操作(在之后的章節(jié)中我會(huì)來分析type_info類文件的源碼)
運(yùn)算 | 描述 |
---|---|
t1 == t2 | 如果兩個(gè)對(duì)象t1和t2類型相同,則返回true;否則返回false |
t1 != t2 | 如果兩個(gè)對(duì)象t1和t2類型不同,則返回true;否則返回false |
t.name() | 返回類型的C-style字符串,類型名字用系統(tǒng)相關(guān)的方法產(chǎn)生1 |
t1.before(t2) | 返回指出t1是否出現(xiàn)在t2之前的bool值 |
type_info類提供了public虛 析構(gòu)函數(shù),以使用戶能夠用其作為基類。它的默認(rèn)構(gòu)造函數(shù)和拷貝構(gòu)造函數(shù)及賦值操作符都定義為private,所以不能定義或復(fù)制type_info類型的對(duì)象。程序中創(chuàng)建type_info對(duì)象的唯一方法是使用typeid操作符(由此可見,如果把typeid看作函數(shù)的話,其應(yīng)該是type_info的 友元)。type_info的name成員函數(shù)返回C-style的字符串,用來表示相應(yīng)的類型名,但務(wù)必注意這個(gè)返回的類型名與程序中使用的相應(yīng)類型名并不一定一致(往往如此,見后面的程序),這具體由編譯器的實(shí)現(xiàn)所決定的,標(biāo)準(zhǔn)只要求實(shí)現(xiàn)為每個(gè)類型返回唯一的字符串。
type_info類源代碼
使用sudo find / -name typeinfo.h來查找源碼
#ifndef _TYPEINFO #define _TYPEINFO #include <exception> namespace std { class type_info { public: virtual ~type_info(); { return __name[0] == '*' ? __name + 1 : __name; } bool before(const type_info& __arg) const { return __name < __arg.__name; } bool operator==(const type_info& __arg) const { return __name == __arg.__name; } bool operator!=(const type_info& __arg) const { return !operator==(__arg); } virtual bool __is_pointer_p() const; virtual bool __is_function_p() const; protected: const char *__name; explicit type_info(const char *__n): __name(__n) { } private: type_info& operator=(const type_info&); type_info(const type_info&); }; } // extern "C++" #endif
示例1-基本數(shù)據(jù)類型
下表列出了使用typeid操作符的表達(dá)式的值
int a; double b; char * c; long d;
運(yùn)算 | 描述 |
---|---|
typeid(a) == typeid(int) | true |
typeid(a) == typeid(float) | false |
typeid(a) == typeid(int *) | false |
typeid(b) == typeid(double) | true |
typeid(b) == typeid(float) | false |
typeid(b) == typeid(long double) | false |
typeid(c) == typeid(char *) | true |
typeid(c) == typeid(char) | false |
typeid(c) == typeid(string) | false |
typeid(d) == typeid(long) | true |
typeid(d) == typeid(int) | false |
操作符typeid返回的是一個(gè)type_info類(用于描述數(shù)據(jù)類型的一個(gè)系統(tǒng)類)對(duì)象的引用。這個(gè)操作符可以用于表達(dá)式和類型名(包括自定的數(shù)據(jù)類型,比如類)。
示例2-類對(duì)象
class base { public : void m(){cout<<"base"<<endl;} }; class derived : public base { public: void m(){cout<<"derived"<<endl;} };
假設(shè)我們根據(jù)例2中定義的兩個(gè)類來定義如下指針:
base * p = new derived;
下表將給出使用typeid操作符的結(jié)果。
運(yùn)算 | 描述 |
---|---|
typeid(p) == typeid(base*) | true |
typeid(p) == typeid(derived*) | false |
typeid(*p) == typeid(base) | true |
typeid(*p) == typeid(derived) | false |
對(duì)于表達(dá)式typeid(p),同樣,因?yàn)閜是base*類型的指針,因此typeid(p) == typeid(base*)為真,而typeid(p) == typeid(derived*)為假。而對(duì)于表達(dá)式typeid(*p),由于此時(shí)的基類不具有多態(tài)性,因而*p將會(huì)采用編譯期類型來計(jì)算,編譯期*p是base對(duì)象,因此表達(dá)式typeid(*p) == typeid(derived)為假,typeid(*p) == typeid(base)為真。
示例3-帶虛函數(shù)的基類
class base { public : virtual void m(){cout<<"base"<<endl;} }; class derived : public base { public: void m(){cout<<"derived"<<endl;} };
假設(shè)我們?nèi)绫纠径x了兩個(gè)類base類和derived類,基于這兩個(gè)類定義,我們定義指針如下:
base * p = new derived;
下表將給出使用typeid操作符的結(jié)果。
運(yùn)算 | 描述 |
---|---|
typeid(p) == typeid(base*) | true |
typeid(p) == typeid(derived*) | false |
typeid(*p) == typeid(base) | false |
typeid(*p) == typeid(derived) | true |
對(duì)于表達(dá)式typeid(p),因?yàn)閜是base*類型的指針,因此typeid(p) == typeid(base*)為真,而typeid(p) == typeid(derived*)為假。而對(duì)于表達(dá)式typeid(*p),因?yàn)閎ase類具有多態(tài)性,因而在計(jì)算typeid(*p)時(shí)會(huì)根據(jù)運(yùn)行時(shí)p所指向的實(shí)際類型去計(jì)算,而本例中p指向的是派生類對(duì)象,因此表達(dá)式typeid(*p) == typeid(derived)為真,typeid(*p) == typeid(base)為假。
異常處理bad_typeid
class bad_typeid : public exception { public: bad_typeid () throw() { } // This declaration is not useless: // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 virtual ~bad_typeid() throw(); // See comment in eh_exception.cc. virtual const char* what() const throw(); }; } // namespace std
以上就是c++ typeid關(guān)鍵字的使用的詳細(xì)內(nèi)容,更多關(guān)于c++ typeid關(guān)鍵字的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)倉(cāng)庫(kù)物資管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)倉(cāng)庫(kù)物資管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12C語(yǔ)言實(shí)現(xiàn)俄羅斯方塊課程設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)俄羅斯方塊課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06C++編譯報(bào)錯(cuò):||error: ld returned 1 exit 
這篇文章主要介紹了C++編譯報(bào)錯(cuò):||error: ld returned 1 exit status|的解決方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01C++實(shí)現(xiàn)四則運(yùn)算器(帶括號(hào))
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)四則運(yùn)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11Qt項(xiàng)目實(shí)戰(zhàn)之實(shí)現(xiàn)MP3音樂播放器
這篇文章主要為大家詳細(xì)介紹了如何利用Qt實(shí)現(xiàn)MP3音樂播放器,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴可以了解一下2023-03-03C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易訂餐系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易訂餐系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06