我们在程序中定义了一个基类,该基类有n个子类,为了方便,我们经常定义一个基类的指针数组,数组中的每一项指向都指向一个子类,那么在程序中我们如何判断这些基类指针是指向哪个子类呢?

本文提供了两种方法 (1) 自定义类id, (2)typeid

一、自定义id

如下所示基类father有两个子类son1 和 son2,我们在基类中定义类虚函数id,子类中分别重载了该函数,各个子类返回值都不同

 class father
{
public:
virtual void fun()
{
cout<<"this is father fun call\n";
}
virtual int id()
{
return ;
}
}; class son1: public father
{
public: void fun()
{
cout<<"this is the son1 fun call\n";
} int id()
{
return ;
} }; class son2: public father
{
public: void fun()
{
cout<<"this is the son2 fun call\n";
} int id()
{
return ;
}
};

通过如下方法我们可以在程序中动态的判断基类指针指向的子类类型

 int main()
{
father * pf;
son1 s1;
son2 s2;
pf = &s1;
if(pf->id() == )
cout<<"this is son1\n";
else cout<<"this is son2\n";
}

二、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 的参数可以使指针,可以使对象,可以是普通变量等。

具体判断基类指针指向的类型方法如下(类的定义同上):

 int main()
{
char sonstr[][];
//由于不知道编译器对typeid.name返回的字符串,因此预先保存好返回的字符串
strcpy(sonstr[], typeid(son1).name());
strcpy(sonstr[], typeid(son2).name());
father * pf;
son1 s1;
son2 s2;
pf = &s1;
if(strcmp(sonstr[], typeid(*pf).name()) == )
{
cout<<"this is son1\n";
}
else if(strcmp(sonstr[], typeid(*pf).name()) == )
{
cout<<"this is son2\n";
} pf = &s2;
if(strcmp(sonstr[], typeid(*pf).name()) == )
{
cout<<"this is son1\n";
}
else if(strcmp(sonstr[], typeid(*pf).name()) == )
{
cout<<"this is son2\n";
}
return ;
}

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

示例:

首先来看typeid操作符,其返回结果是名为type_info的标准库类型的对象的引用。type_info中存储特定类型的有关信息,定义在typeinfo头文件中。

下面来看typeid().name(),用于获得表达式的类型,以c-style字符串形式返回类型名。用法示例如下。 
注意:对非引用类型,typeid().name()是在编译时期识别的,只有引用类型才会在运行时识别。

 #include<iostream>
#include <typeinfo>
using namespace std; class Class1{};
class Class2:public Class1{};
void fn0();
int fn1(int n); int main(void)
{
int a = ;
int* b = &a;
float c;
double d; cout << typeid(a).name() << endl;
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
cout << typeid(Class1).name() << endl;
cout << typeid(Class2).name() << endl;
cout << typeid(fn0).name() << endl;
cout << typeid(fn1).name() << endl;
cout << typeid(typeid(a).name()).name() << endl;
system("pause");
}

结果如下:

 int
int *
float
double
class Class1
class Class2
void __cdecl(void)
int __cdecl(int)
char const *
请按任意键继续. . .

可以看到,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)的更多相关文章

  1. c++基类指针指向继承类调用继承类函数

      类里面重载运算符>>, 需要使用友元函数,而友元函数,不能作为虚函数. 所以,基类指针无法直接调用继承类里重构的 >>  ; 使用类转换,能解决掉,基类指针 调用 继承类 ...

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

    基类指针指向派生类,我们已经很熟了.假如我们想用派生类反过来指向基类,就需要有两个要求:1)马克-to-win:基类指针开始时指向派生类,2)我们还需要清清楚楚的转型一下. if you want t ...

  3. 虚析构函数? vptr? 指针偏移?多态数组? delete 基类指针 内存泄漏?崩溃?

    五条基本规则: 1.如果基类已经插入了vptr, 则派生类将继承和重用该vptr.vptr(一般在对象内存模型的顶部)必须随着对象类型的变化而不断地改变它的指向,以保证其值和当前对象的实际类型是一致的 ...

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

    大家对虚表并不陌生,都知道每个含有虚函数的类对象都有1个虚指针,但是在现实使用中,却总是因为这而调试半天,才发现原来是虚指针惹的祸.我这几天在调试代码时候也中招了,我的问题是这样的,如下图,CTree ...

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

    基类指针和子类指针之间相互赋值(1)将子类指针赋值给基类指针时,不需要进行强制类型转换,C++编译器将自动进行类型转换.因为子类对象也是一个基类对象. (2)将基类指针赋值给子类指针时,需要进行强制类 ...

  6. C++ 基类指针和子类指针相互赋值

    首先,给出基类animal和子类fish [cpp] view plaincopy //======================================================== ...

  7. 当this指针成为指向之类的基类指针时,也能形成多态

    this指针: 1)对象中没有函数,只有成员变量 2)对象调用函数,通过this指针告诉函数是哪个对象自己谁. #include<iostream> using namespace std ...

  8. C++获取基类指针所指子类对象的类名

    我们在程序中定义了一个基类,该基类有n个子类,为了方便,我们经常定义一个基类的指针数组,数组中的每一项指向都指向一个子类,那么在程序中我们如何判断这些基类指针是指向哪个子类呢? 关键字 typeid, ...

  9. C++基础知识 基类指针、虚函数、多态性、纯虚函数、虚析构

    一.基类指针.派生类指针 父类指针可以new一个子类对象 二.虚函数 有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数? 有解决方案,这个对象指针必须是一个父类类型 ...

随机推荐

  1. go协程使用陷阱(转)

    协程中使用全局变量.局部变量.指针.map.切片等作为参数时需要注意,此变量的值变化问题. 与for 循环,搭配使用更需谨慎. 1,内置函数时直接使用局部变量,未进行参数传递 package main ...

  2. 安卓工作室 文件浏览器 android studio File browser

    安卓工作室 文件浏览器 android studio  File browser 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱:313134555@qq.com E-mail: ...

  3. C语言---斐波那契问题

      最近学习了一个叫递归的概念,里面最著名的一个例子就是斐波那契问题,觉得很有意思,就来实现一下: 什么是斐波那契数列   斐波那契数列,又称黄金分割数列,值得这样一个数列:0.1.1.3.5.8.1 ...

  4. Sql Server 修改表所属用户

    Sql Server 修改表所属用户 exec sp_changeobjectowner 'tablename','dbo' tablename--所要修改的表明 dbo--是表所属的用户,默认是db ...

  5. vs配置TFS

  6. js获取本机id

    var hostname = location.hostname; window.location.href="http://"+hostname+":8080/zhib ...

  7. Android笔记(四):RecyclerView

    RecyclerView是ListView的增强版.有了它之后,你就可以抛弃ListView了. recycle,重复利用.在ListView里,我们得自己写重复利用View的代码,而Recycler ...

  8. request.getParameter(“xxx”)的参数的取值

    request.getParameter(“xxx”)的参数的取值的几种可能: 1. Html中form表单中标签的name属性: <form name="form" met ...

  9. 深入理解Git (一) - 元数据

    三分钟教你学Git仅仅是教我们会用Git了,但是内部的一些实现原理假设我们也知道一些的话会使我们使用起来更加顺手.这个系列就是在你用了Git一段时间之后,并想继续到Git的内部看一下到底而准备的. G ...

  10. Spring.profiles多环境配置最佳实践

    转自:https://www.cnblogs.com/jason0529/p/6567373.html Spring的profiles机制,是应对多环境下面的一个解决方案,比较常见的是开发和测试环境的 ...