首页 > 其他分享 >RTTI运行时类型识别

RTTI运行时类型识别

时间:2022-10-13 12:07:29浏览次数:40  
标签:typeid 识别 const cout pb pa 类型 RTTI type


        RTTI是Runtime Type Identification的缩写,是“运行时类型识别”的意思。面向对象的编程语言,象C++,​​Java​​,Delphi都提供了对RTTI的支持。 本文将简略介绍 RTTI 的一些背景知识、描述 RTTI 的概念,并通过具体例子和代码介绍什么时候使用以及如何使用 RTTI。本文还将详细描述两个重要的 RTTI 运算符的使用方法,它们是 typeid 和dynamic_cast。

1. typeid的用法

 

    typeid 的结果是 const type_info&。所以下面先对type_info类作下介绍:

class type_info {
public:
virtual ~type_info();
size_t hash_code() const
_CRTIMP_PURE bool operator==(const type_info& rhs) const;
_CRTIMP_PURE bool operator!=(const type_info& rhs) const;
_CRTIMP_PURE int before(const type_info& rhs) const;
_CRTIMP_PURE const char* name() const;
_CRTIMP_PURE const char* raw_name() const;
};


        我们不能直接实例化 type_info 类的对象,因为该类只有一个私有复制构造函数。 构造(临时)type_info 对象的唯一方式是使用 typeid 运算符。 由于赋值运算符也是私有的,因此不能复制或分配类 type_info 的对象。

1.2typeid应用实例

1.2.1typeid静态的类型判断

        typeid可以静态地确定操作数的类型,也可以动态地确定操作数的类型,这取决于操作数本身是否拥有虚函数。当typeid的操作数是一个基本类型的变量,或者是一个不带虚函数的对象时,typeid的运行结果是在编译阶段决定的。所以是一种静态的类型判断。见下面的例子。

#include <iostream>
using namespace std;


class A{
int i;
public:
void show(){
cout<<"In class A"<<endl;
}
};


class B{
int i;
public:
void show(){
cout<<"In class B"<<endl;
}
};

template < typename T>void func(T& a){
if(typeid(A)==typeid(T))
cout<<"is A"<<endl;
if(typeid(B)==typeid(T))
cout<<"is B"<<endl;
}

int main(){
if(typeid(B)==typeid(A))
cout<<"A equal to B"<<endl;
else
cout<<"A not equal to B"<<endl;

A a;
B b;
func<B>(b);
func<B>(b);
cout<<typeid(B).name()<<endl;
getchar();
}

程序输出结果: 

A not equal to B 

is B 

is B 

class B

        在上面的程序中,函数模板func()被实例化为class A和class B时,typeid(T)是在编译阶段静态确定的。在函数模板内部,可以通过typeid操作决定在模板参数被实例化为不同数据类型的时要采取不同的行动。

1.22typeid动态类型判断

typeid更多的时候是在运行时用来动态地确定指针或引用所指向对象的类型,这时要求typeid所操作的对象一定要拥有虚函数。见下面的程序。

#include <iostream>
using namespace std;

class A{
virtual void func(){}
};

class B:public A{};

void reportA(A* pa){
if(typeid(*pa)==typeid(A))
cout<<"Type of *pb is A"<<endl;
else if(typeid(*pa)==typeid(B))
cout<<"Type of *pb is B"<<endl;
}

void reportB(B* pb){
if(typeid(*pb)==typeid(A))
cout<<"Type of *pb is A"<<endl;
else if(typeid(*pb)==typeid(B))
cout<<"Type of *pb is B"<<endl;
}

int main(){
A a,*pa;
B b,*pb;
pa=&a;
reportA(pa);
pa=&b;
reportA(pa);
pb=static_cast<B*>(&a);
reportB(pb);
pb=&b;
reportB(pb);
}

程序输出结果: 

Type of *pb is A 

Type of *pb is B 

Type of *pb is A 

Type of *pb is B

        从上面的运行结果可以看出,使用typeid确实能够在程序运行期间动态地判断指针所指对象的实际类型。使用引用可以到达同样的效果,因为引用的底层实现就是指针。

要注意的是, 

    (1)如果在Class A的定义中,将函数func()定义为普通函数(即将前面的virtual关键字去掉),那么typeid(*pa)的结果永远是typeid(A),而typeid(*pb)的结果永远是typeid(B)。也就是说,由于pa和pb所指向的对象中没有虚函数,该对象就没有虚函数表存放运行时信息,typeid实际就变成了一种静态运算符。

    (2)C++中的一切“动态”机制,包括虚函数、RTTI等,都必须通过指针或引用来实现。换句话说,指针所指的对象或引用所绑定的对象,在运行阶段可能与声明指针或引用时的类型不一致。如果不使用指针或引用,而是直接通过对象名访问对象,那么及时对象拥有动态信息(虚函数表),对象的动态信息与静态申明对象时的信息必然一致,就没有必要访问虚函数表;而如果对象不拥有虚函数,就没有虚函数表存放动态信息,也就无法在运行时动态判断指针所指向对象(或引用所绑定对象)的实际类型。

标签:typeid,识别,const,cout,pb,pa,类型,RTTI,type
From: https://blog.51cto.com/u_12704841/5753041

相关文章

  • 中文命名实体识别的实战代码
    基于BERT预训练的中文命名实体识别TensorFlow实现​​https://github.com/wusaisa/BERT-BiLSTM-CRF-NER​​用深度学习做命名实体识别​​​https://www.jianshu.com/p/495c......
  • element-ui的el-input设置number类型后的相关问题
    element-ui的el-input,设置type="number"后,后边会多一个上下箭头,并且在中文输入法输入数据的时候,光标上移!! 前端的强迫症啊(凭啥你这输入框和别人的不一样,凭啥你光标就......
  • mysql中timestamp和datetime类型的区别
    一、MySQL中表示当前时间的方法:CURRENT_TIMESTAMPCURRENT_TIMESTAMP()NOW()LOCALTIMELOCALTIME()LOCALTIMESTAMPLOCALTIMESTAMP()二、关于TIMESTAMP和DATETIME的比较一个完......
  • GO语言基本数据类型
    Go语言-程序实体与关键字任何Go语言源码文件都由若干个程序实体组成的。在Go语言中,变量、常量、函数、结构体和接口被统称为“程序实体”,而它们的名字被统称为“标识符”。......
  • Kubernetes--Ingress资源类型
    Ingress资源类型基于HTTP暴露的每个Service资源均可发布于一个独立的FQDN主机名之上,如“www.ik8s.io”;也可发布于某主机上的URL路径之上,从而将它们整合到同一个Web站......
  • JTable实现Integer和Double数据类型的列,只能输入符合标准的值
    如下图,该列的数据类型为Integer类,则不能输入Double和字符串类型的内容如何设定表格的列的类型?publicDefaultTableModeltableModelInstance(){ returnnewDefa......
  • python基础-数字类型
    1.数字的简单运算  常用运算符    +,-,*, /,%,//,**        =就是赋值运算符,在变量介绍中已提及过,a=13;    这里要说下赋值运算符的参数运算,......
  • 协变返回类型
    1.代码示例packagedemo01;classGrain{@OverridepublicStringtoString(){return"Grain[]";}}classWheatextendsGrain{......
  • oracle修改字段类型报错ORA-01439: column to be modified must be empty to change d
    可用如下方式,都是一样的,修改字段类型的列的数据必须为空!ORA-01440:要减小精度或标度,则要修改的列必须为空问题修复-信铁寒胜-博客园(cnblogs.com) ......
  • python基础-较复杂数据类型预览
    1.初识列表  列表就是队列;  列表是一种有序的,且内容可重复的数据类型;  用list代表列表,也可以用list()定义一个列表,同时定义列表可以直接使用[];  python中列......