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\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

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

时间: 2024-11-07 10:37:38

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

C++ typeid动态判断基类指针指向的子类类型

typeid是c++的关键字,typeid操作符的返回结果是名为type_info的标准库类型的对象的引用(在头文件typeinfo中定义) ISO C++标准并没有确切定义type_info,它的确切定义编译器相关的,但是标准却规定了其实现必需提供如下四种操作: type_info类提供了public虚 析构函数,以使用户能够用其作为基类.它的默认构造函数和拷贝构造函数及赋值操作符都定义为private,所以不能定义或复制type_info类型的对象. 程序中创建type_info对象的唯一方

C++基类指针指向的派生类对象内存的释放

C++由于基类指针可以指向不同的派生类对象,因此当赋予基类指针不同的地址时,要注意之前的派生类对象的内存释放. int main(){ Parent* ptr = new Child1; Child2 myChild2; Child3 myChild3; ptr->show(); delete ptr; //位置1 ptr = &myChild2; ptr->show(); delete ptr; //位置2 ptr = &myChild3; ptr->show(); d

简单工厂类,有继承、虚函数重写、基类指针指向子类对象会发生多态(1)

class Fruit { public: virtual void get_fruit() { std::cout<<"Fruit:getFruit"<<std::endl; } }; class Pear : public Fruit { public: virtual void get_fruit() { std::cout<<"Pear:getFruit"<<std::endl; } }; class Bana

面向对象--多继承&amp;派生类对象内存布局分析&amp;各基类指针所指向的位置分析

背景 原文链接:ordeder  http://blog.csdn.net/ordeder/article/details/25477363 关于非虚函数的成员函数的调用机制,可以参考: http://blog.csdn.net/yuanyirui/article/details/4594805 成员函数的调用涉及到面向对象语言的反射机制. 虚函数表机制可以查看下面这个blog: http://blog.csdn.net/haoel/article/details/1948051 总结为: 其一

何使用派生类指针指向基类,即downcast向下转型?

基类指针指向派生类,我们已经很熟了.(视频下载) (全部书籍)假如我们想用派生类反过来指向基类,就需要有两个要求:1)马克-to-win:基类指针开始时指向派生类,2)我们还需要清清楚楚的转型一下. if you want to use derived class pointer point to base class, there are two requirements: 1) base class pointer is initially the type of the derived c

c++之虚函数和基类指针

1. 基类指针虽然获取派生类对象地址,却只能访问派生类从基类继承的成员 1 #include <iostream> 2 using namespace std; 3 4 //通过基类指针只能访问从基类继承的成员 5 class A 6 { 7 public: 8 A(char x) 9 { 10 this->x = x; 11 } 12 //void virtual who() //基类定义虚函数,则派生类的重定义版本默认为虚函数 13 void who() //除非定义虚函数,否则基类

派生类地址比基类地址少4(子类与基类指针强行转换的时候,值居然会发生变化,不知道Delphi BCB是不是也这样) good

大家对虚表并不陌生,都知道每个含有虚函数的类对象都有1个虚指针,但是在现实使用中,却总是因为这而调试半天,才发现原来是虚指针惹的祸.我这几天在调试代码时候也中招了,我的问题是这样的,如下图,CTree是最底层基类(非虚类), CSamplerTree(虚类)派生自CTree,CMSamplerTree,CASamplerTree派生自CSamplerTree,                                                         CTree中包括两个成员

C++ 基类指针,子类指针,多态

基类指针和子类指针之间相互赋值(1)将子类指针赋值给基类指针时,不需要进行强制类型转换,C++编译器将自动进行类型转换.因为子类对象也是一个基类对象. (2)将基类指针赋值给子类指针时,需要进行强制类型转换,C++编译器将不自动进行类型转换.因为基类对象不是一个子类对象.子类对象的自增部分是基类不具有的.(强制转换告诉编译器为对象增加子类所特有的部分) fish* fh1;  animal* an1 = new animal; fh1 = (fish*)an1; 原理: 当我们构造fish类的对

基类指针和派生类指针的使用总结

1 基类指针指向基类对象(正常使用) 2 派生类指针指向派生类对象(正常使用,不管是不是虚函数,调用的都是派生类的函数) 3 基类指针指向派生类对象(多态的体现,虚函数的话调用的是派生类的,非虚函数的话调用的是基类的) 4 派生类指针指向基类对象(一般不要这么用) 参考资料: http://blog.csdn.net/monkeyduck/article/details/15506435 [c++]实例演示类继承中派生类到基类的转换及虚函数 基类指针和派生类指针的使用总结