1. 程式人生 > >c++ 動態判斷基類指針指向的子類類型(typeid)

c++ 動態判斷基類指針指向的子類類型(typeid)

main 應該 中間 函數返回 rtu char 例如 fat 由於

我們在程序中定義了一個基類,該基類有n個子類,為了方便,我們經常定義一個基類的指針數組,數組中的每一項指向都指向一個子類,那麽在程序中我們如何判斷這些基類指針是指向哪個子類呢?

本文提供了兩種方法 (1) 自定義類id, (2)typeid

一、自定義id

如下所示基類father有兩個子類son1 和 son2,我們在基類中定義類虛函數id,子類中分別重載了該函數,各個子類返回值都不同

 1 class father
 2 {
 3 public:
 4     virtual void fun()
 5     {
 6         cout<<"this is father fun call\n
"; 7 } 8 virtual int id() 9 { 10 return 0; 11 } 12 }; 13 14 class son1: public father 15 { 16 public: 17 18 void fun() 19 { 20 cout<<"this is the son1 fun call\n"; 21 } 22 23 int id() 24 { 25 return 1; 26 }
27 28 }; 29 30 class son2: public father 31 { 32 public: 33 34 void fun() 35 { 36 cout<<"this is the son2 fun call\n"; 37 } 38 39 int id() 40 { 41 return 2; 42 } 43 };

通過如下方法我們可以在程序中動態的判斷基類指針指向的子類類型

 1 int main()
 2 {
 3     father * pf;
4 son1 s1; 5 son2 s2; 6 pf = &s1; 7 if(pf->id() == 1) 8 cout<<"this is son1\n"; 9 else cout<<"this is son2\n"; 10 }

二、typeid

typeid是c++的關鍵字,typeid操作符的返回結果是名為type_info的標準庫類型的對象的引用(在頭文件typeinfo中定義)

ISO C++標準並沒有確切定義type_info,它的確切定義編譯器相關的,但是標準卻規定了其實現必需提供如下四種操作:

技術分享圖片

type_info類提供了public虛 析構函數,以使用戶能夠用其作為基類。它的默認構造函數和拷貝構造函數及賦值操作符都定義為private,所以不能定義或復制type_info類型的對象。

程序中創建type_info對象的唯一方法是使用typeid操作符(由此可見,如果把typeid看作函數的話,其應該是type_info的 友元)

type_info的name成員函數返回C-style的字符串,用來表示相應的類型名,但務必註意這個返回的類型名與程序中使用的相應類型名並不一定一致,這具體由編譯器的實現所決定的,標準只要求實現為每個類型返回唯一的字符串

typeid 的參數可以使指針,可以使對象,可以是普通變量等。

具體判斷基類指針指向的類型方法如下(類的定義同上):

 1 int main()
 2 {
 3     char sonstr[2][100];
 4     //由於不知道編譯器對typeid.name返回的字符串,因此預先保存好返回的字符串
 5     strcpy(sonstr[0], typeid(son1).name());
 6     strcpy(sonstr[1], typeid(son2).name());
 7     father * pf;
 8     son1 s1;
 9     son2 s2;
10     pf = &s1;
11     if(strcmp(sonstr[0], typeid(*pf).name()) == 0)
12     {
13         cout<<"this is son1\n";
14     }
15     else if(strcmp(sonstr[1], typeid(*pf).name()) == 0)
16     {
17         cout<<"this is son2\n";
18     }
19 
20     pf = &s2;
21     if(strcmp(sonstr[0], typeid(*pf).name()) == 0)
22     {
23         cout<<"this is son1\n";
24     }
25     else if(strcmp(sonstr[1], typeid(*pf).name()) == 0)
26     {
27         cout<<"this is son2\n";
28     }
29     return 0;
30 }

轉自:https://www.cnblogs.com/TenosDoIt/p/3176525.html

示例:

首先來看typeid操作符,其返回結果是名為type_info的標準庫類型的對象的引用。type_info中存儲特定類型的有關信息,定義在typeinfo頭文件中。

下面來看typeid().name(),用於獲得表達式的類型,以c-style字符串形式返回類型名。用法示例如下。
註意:對非引用類型,typeid().name()是在編譯時期識別的,只有引用類型才會在運行時識別。

 1 #include<iostream>  
 2 #include <typeinfo>  
 3 using namespace std;  
 4 
 5 class Class1{};
 6 class Class2:public Class1{};
 7 void fn0();
 8 int fn1(int n);
 9 
10 int main(void)  
11 {  
12     int a = 10;
13     int* b = &a;
14     float c;
15     double d;
16 
17     cout << typeid(a).name() << endl;
18     cout << typeid(b).name() << endl;
19     cout << typeid(c).name() << endl;
20     cout << typeid(d).name() << endl;
21     cout << typeid(Class1).name() << endl;
22     cout << typeid(Class2).name() << endl;
23     cout << typeid(fn0).name() << endl;
24     cout << typeid(fn1).name() << endl;
25     cout << typeid(typeid(a).name()).name() << endl;
26     system("pause");
27 }  

結果如下:

 1 int
 2 int *
 3 float
 4 double
 5 class Class1
 6 class Class2
 7 void __cdecl(void)
 8 int __cdecl(int)
 9 char const *
10 請按任意鍵繼續. . .

可以看到,typeid().name()可以返回變量、函數、類的數據類型名,功能是相當強大的。
cout << typeid(typeid(a).name()).name() << endl;可以看到結果為char const *,因此typeid().name()返回了存儲類型名的字符串。
之前看有腦洞大的網友在一篇博客中問能夠使用typeid().name()返回值作為類型名進行定義
typeid(a).name() b;//error!。這個想法其實很不錯,我們在寫代碼的時候很可能需要設很多中間變量,如果不是自己寫的代碼,確定變量類型是很麻煩的。
來解答下這個問題。用typeid().name()定義肯定是不行的,通過上面的返回結果就可以解釋,typeid().name()返回的是字符串,肯定是不能用於定義的。

轉自:https://blog.csdn.net/lin453701006/article/details/73972184

c++ 動態判斷基類指針指向的子類類型(typeid)