RTTI(Run-Time Type Identification),通过运行时类型信息程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。
RTTI 翻译过来是运行时类型信息。一个引用不仅可以指向和自己类型一致的对象,还可以指向自己子类的对象。那么JVM在执行代码时是如何判定引用指向的对象是否合法?这时就需要用到RTTI。
如何查看RTTI
查看一个引用的RTTI和class对象密不可分,这个对象是一个特殊对象,和类同生共死。class对象中包含了类的所有信息,比如类名。当我们编译一个类后,编译器会生成相应的class对象,并将该类和class对象一同写到了.class文件中。当类加载器加载类时会连同class对象一同加载到内存。而当我们创建对象时,JVM虚拟机是根据class对象创建出普通对象。因此,普通对象中将会持有class对象的引用。现在事情就很简单了,JVM通过引用找到普通对象,通过普通对象中的引用找到class对象,通过class对象查到了类信息,这时一个引用的RTTI就被获得了。
获取RTTI
RTTI用于描述class对象信息,Java中也为程序员提供了获取RTTI的接口
Object obj = new Base();
Class<?> c = obj.getClass(); //返回class对象引用
上面的代码我们获取了class对象,而obj的RTTI就在c中
前面提到对象都是通过class对象创建出来的,因此我们可以采用别的方式来创建对象,下面是一个小例子:
Class<?> baseClass = Class.forName(“Base”); //返回class对象引用
Base base = baseClass.newInstance();
RTTI的表现形式
以下行为会查看RTTI:
向下转型,A a = (B) b;
获取Class对象,Class<?> c = a.getClass();
对于关键字instanceof的使用,instanceof主要用来查看一个对象是否属于某个类
反射
要讲反射首先要将RTTI和反射的应用场景搞清楚。反射和RTTI是没有直接关系的,只不过因为反射也涉及到类型信息才放到这里讲。
RTTI的应用场景是这样的:给一个引用,然后识别这个引用的类型信息,它需要建立在类已知的基础上,即编译器见过这个类,那么JVM或者在我们代码中才能获取一个引用的RTTI。
通过反射也能获取类型信息,它是在我们不知道类信息的基础上来做的。比如某个类没有在本地存储,而是在将来的某个时刻会通过网络发送过来。那么我们在代码中无法通过new的方式来创建这个类的对象,也不能调用其方法(如果这样做,编译器会报错说找不到该类),这时就需要用到反射了。
RTTI提供了以下两个非常有用的操作符:
(1)typeid操作符,返回指针和引用所指的实际类型。
(2)dynamic_cast操作符,将基类类型的指针或引用安全地转换为派生类型的指针或引用。
面向对象的编程语言,像C++,Java,delphi都提供了对RTTI的支持。 本文将简略介绍 RTTI 的一些背景知识、描述 RTTI 的概念,并通过具体例子和代码介绍什么时候使用以及如何使用 RTTI;本文还将详细描述两个重要的 RTTI 运算符的使用方法,它们是 typeid 和dynamic_cast。
其实,RTTI 在C++中并不是什么新的东西,它早在十多年以前就已经出现了。但是大多数开发人员,包括许多高层次的C++程序员对它并不怎么熟悉,更不用说使用 RTTI 来设计和编写应用程序了。
一些面向对象专家在传播自己的设计理念时,大多都主张在设计和开发中明智地使用虚拟成员函数,而不用 RTTI 机制。但是,在很多情况下,虚拟函数无法克服本身的局限。每每涉及到处理异类容器和根基类层次(如 MFC)时,不可避免要对对象类型进行动态判断,也就是动态类型的侦测。如何确定对象的动态类型呢?答案是使用内建的 RTTI 中的运算符:typeid 和 dynamic_cast。
在C++中存在虚函数,也就存在了多态性,对于多态性的对象,在程序编译时可能会出现无法确定对象的类型的情况。当类中含有虚函数时,其基类的指针就可以指向任何派生类的对象,这时就有可能不知道基类指针到底指向的是哪个对象的情况,类型的确定要在运行时利用运行时类型标识做出。为了获得一个对象的类型可以使用typeid函数,该函数返回一个对type_info类对象的引用,要使用typeid必须使用头文件
typeid操作符
该操作符的主要作用就是让用户知道当前的变量是什么类型的,比如使用typeid(a).name()就能知道变量a是什么类型的。因为typeid()操作符是一个返回类型为const typeid_info&类型的操作符,所以下面先对type_info类作下介绍
C++ 中RTTI的使用方法详解
RTTI是运行阶段类型识别(Runtime Type Identification)的简称。这是新添加到c++中的特性之一,很多老式实现不支持。另一些实现可能包含开关RTTI的编译器设置。RTTI旨在为程序在运行阶段确定对象类型提供一种标准方式。很多类库已经成为其父类对象提供了实现这种方式的功能。但由于c++内部并不支持,因此各个厂商的机制通常互不兼容。创建一种RTTI语言标准将使得未来的库能够彼此兼容。
c++有3个支持RTTI的元素
如果可能的话,dynamic_cast 运算符将使用一个指向基类的指针来生成一个指向派生类的指针;否则,该运算符返回0——空指针
typied运算符返回一个指出对象的类型的值
type_info结构存储了有关特定类型的信息