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

摘要:
确定基类指针指向的类型的具体方法如下:1itmin()2{3charsonstr[2][100];4//由于编译器返回的typeid.name字符串未知,因此返回的字符串5strcpy;6strcpy,7father*pf;8son1s1;9son2s2;10pf=&s1;11if12{13cout<<“thison1”;14}15 elsei16{17cout<“thisson”;18}1920pf=&s2;如果22{23 cout˂˂“this isson1”;24}25否则,26{27 cout˂“this ison2”;28}29返回0;30}转移自:https://www.cnblogs.com/TenosDoIt/p/3176525.html示例:首先,查看typeid运算符,其返回结果名为type_Info。接下来,让我们看看typeid()。name(),用于获取表达式的类型并以c样式字符串的形式返回类型名称。

我们在程序中定义了一个基类,该基类有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,它的确切定义编译器相关的,但是标准却规定了其实现必需提供如下四种操作:

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

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

免责声明:文章转载自《c++ 动态判断基类指针指向的子类类型(typeid)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇TCP套接字选项SO_LINGER与TCP_LINGER2未能加载文件或程序集“log4net,下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

为何将未被初始化的Integer变量赋值给int变量时会抛出空指针异常?

Integer的NullPointerException 学习包装类的时候看到这样一个问题: public class TestBox { Integer i; int j; public void go(){ j = i;//第七行 System.out.println(j);...

转载别人的DLL DEll研究

昨日,编了个DLL和EXE来进行了下测试,exe通过lib静态联编dll,来调用它的导出类,当改变DLL中导出类的结构(eg.成员变量的顺序等),从新发布DLL而不从新联结编译EXE,就会造成错误的执行结果或崩溃!通过观察DLL和EXE生成的汇编代码,才知道生成的机器码中并无类的成员变量,只有类的Size(根据成员变量和有无虚函数)和类函数代码。    函...

C++中点操作符和箭头操作符

区别 C++中对于类来说,对于其中的成员,用点操作符.来获得, 而对于一个指向类对象的指针来说,则用箭头操作符->调用该指针所指向对象的成员。 当类定义->重载操作符后,则既可以用箭头操作符,也可以用点操作符。 重载->操作符 重载箭头操作符必须定义为类成员函数。没有显式形参(而且是类成员,唯一隐式形参是this)。->的右操作数不...

C++风格与C风格文件读写效率测试-vs2015,vs2017

1 void test_write() 2 { 3 const int TEST_SIZE = 100000000; 4 const char* c_plus_write_file = "H://c_plus_write_file.txt"; 5 const char* c_write_file = "g://c_writ...

Delphi的字符(Char),字符串(String),字符串指针(PChar),字符数组arrayofchar(来自http://delphi.cjcsoft.net/论坛)

Delphi有三种类型的字符: AnsiChar这是标准的1字节的ANSI字符,程序员都对它比较熟悉。 WideChar这是2字节的Unicode字符。 Char在目前相当于AnsiChar,但在Delphi 2010 以后版本中相当于WideChar. 记住因为一个字符在长度上并不表示一个字节,所以不能在应用程序中对字符长度进行硬编码, 而应该使用Siz...

Freertos学习:07-队列

--- title: rtos-freertos-07-队列 EntryName : rtos-freertos-07 date: 2020-06-23 09:43:28 categories: tags: - ipc - queue - freertos --- 章节概述: 介绍 FreeRTOS中的任务间通讯机制:队列的使用(尽管FreeRTOS中没有...