c++ 动态判断基类指针指向的子类类型(typeid)

我们在程序中定义了一个基类,该基类有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
";
 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
";
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
";
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
";
 9     else cout<<"this is son2
";
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
";
14     }
15     else if(strcmp(sonstr[1], typeid(*pf).name()) == 0)
16     {
17         cout<<"this is son2
";
18     }
19 
20     pf = &s2;
21     if(strcmp(sonstr[0], typeid(*pf).name()) == 0)
22     {
23         cout<<"this is son1
";
24     }
25     else if(strcmp(sonstr[1], typeid(*pf).name()) == 0)
26     {
27         cout<<"this is son2
";
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

原文地址:https://www.cnblogs.com/liushui-sky/p/9638507.html