我们在程序中定义了一个基类,该基类有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. BZOJ1395 : [Baltic2005]Trip

    建立新图,原图中每条边在新图中是点,新图中每个点的点权为$-e[i].c+e[i].b$,边权为$0$. 若$e[i].d\leq e[j].a$,则连一条$i$到$j$的单向边. 对于原图中每个点, ...

  2. JDBC(2)—Statement

    介绍: 获取到数据库连接之后,就可以对数据库进行一些增.删.改操作,但是却不能进行查询操作. 增删改操作是程序到数据库的一个操作过程,但是查询是程序到数据库--数据库返回到程序的一个过程. 步骤: 步 ...

  3. 使用Date和SimpleDateFormat类表示时间

    Date类: 使用 Date 类的默认无参构造方法创建出的对象就代表当前时间,我们可以直接输出 Date 对象显示当前的时间,显示的结果如下: Date d = new Date(); System. ...

  4. 回顾MySQL中的事务特征

    一.事务定义Transaction事务:一个最小的不可再分的工作单元:通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元)一个完整的业务需要批量的DML(insert. ...

  5. 10个提升MySQL性能的小技巧

    从工作量分析到索引的三条规则,这些专家见解肯定会让您的MySQL服务器尖叫. 在所有的关系数据库中,MySQL已经被证明了完全是一头野兽,只要通知停止运行就绝对不会让你多等一秒钟,使你的应用置于困境之 ...

  6. centos7 apache设置伪静态 开启rewrite_module

    设置伪静态除了要生成.htaccess文件外,还需要查看服务器是否开启了rewrite_module.经过一番的纠结,处理方法如下: 编辑Apache配置文件 nano /etc/httpd/conf ...

  7. 数据库 简介 升级 SQLite 总结 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  8. [Algorithm] Calculate Pow(x,n) using recursion

    Asking you to implement the Math.pow method The navie implemenation can be: // O(N) const pow1 = (x, ...

  9. JS中的HTML片段

    经常在js里面写一些html模板,但是由于语法不同,没有办法啊直接将html黏贴在js中. var html = "<!DOCTYPE html>"+ "&l ...

  10. springboot mybatis pagehelper 分页问题

    1:添加依赖 compile group: 'com.github.pagehelper', name: 'pagehelper-spring-boot-starter', version: '1.2 ...