C++ RTTI 机制
来源:互联网 发布:类似photosynth的软件 编辑:程序博客网 时间:2024/06/06 07:11
RTTI(Run Time Type information): 是编译器在 编译期间 生成的特殊类型信息(type_info),包括对象继承关系,对象本身的描述,RTTI 是为多态而生成的信息,所以 只有具有虚函数的对象才会生成 RTTI。
在 C++ 中,有以下两个函数用于 运行时类型检测:
一、dynamic_cast
语法:
dynamic_cast < new_type > ( expression )
返回类型为 new_type 的值 或 抛出一个异常。
new_type
new_type 必须是指向完整类类型或 void * 的指针或引用。必须是类的指针或引用,或 void*。因为没有对 void 的引用。
expression
expression 必须是指向完整类类型的指针或引用。而且,expression 所代表的类必须包含虚函数。
如果转换成功,dynamic_cast 将返回一个 new_type 的值。 如果转换失败,而且 new_type 是指针,那么将返回NULL; 而如果 new_type 是引用,那么将抛出异常 std::bad_cast。
1.1 实现原理
在 C++ 对象模型 中 , 我们知道,在包含虚函数的类中,会产生一张虚函数表,而虚函数表的前面,还会有一部分额外的信息,用于记录与类相关的信息 —— type_info,比如说,对象继承关系,对象本身的描述等等。
dynamic_cast 能否转换成功,所依据的就是这一部分 type_info 信息。具体可参考 C++ dynamic_cast实现原理
dynamic_cast 的时间和空间代价是相对较高的,在设计时应避免使用。可参考 How expensive is RTTI?
如果整个工程都不需要 dynamic_cast,可以禁用运行时类型信息(vs2008默认是启用的)。
禁用方法如下:
依次选择【工程属性】、【配置属性】、【C/C++】、【语言】。将【启用运行时类型信息】改为”否“。
1.2 应用场景
dynamic_cast 常用于有“父子”关系的两个类对象指针或引用之间进行转换。而且,只能在有虚函数的类层次之间使用 dynamic_cast 。
如下一段代码:
class Interface{public: virtual void GenericOp() = 0;};class SpecificClass : public Interface{public: virtual void GenericOp(); virtual void SpecificOp();};
我们定义一个Interface
类型的指针:
Interface * ptr = new SpecificClass; // 可以用基类指针指向派生类对象,因为这是安全的。// 而不能用派生类指针指向基类对象,因为可能调用基类不存在的方法,是不安全的。
ptr 指针指向的实际类型是 SpecificClass 对象,如果我们希望通过 ptr 指针调用 SpecificClass::SpecificOp 方法,为了保证基类指针顺利安全的调用派生类方法。需要使用 dynamic_cast 进行动态类型转换:
SpecificClass* ptr_spec = dynamic_cast < SpecificClass * >(ptr);if( ptr_spec ){ ptr_spec->SpecificOp();}else{ ptr->GenericOp();};
dynamic_cast 是如何保证安全的? dynamic_cast 会对待检测指针进行类型检测,只有 ptr 指向的对象确实是 SpecificClass 类型(或者包含) ,才能成功转换,否则返回 NULL 或者 抛出 std::bad_cast
异常(当转换对象为NULL的引用)。
dynamic_cast 小结:
没有虚函数,不能动态转换。
转换的依据是,type_info 信息。
如果 expression 所指对象的实际类型就是 new_type,则转换成功。 如: 基类指针(假如指向派生类对象),转换为派生类对象时,转换成功。
如果 expression 所指对象的实际类型“包含” new_type,则转换成功。 如:A 派生了 B, B 派生了 C,
A * ap = new C; B * bp = dynamic<B*>(ap) ;
。如果 expression 和 new_type 之间毫无关系,则转换失败。
expression 指向的类一定要包含虚函数,否则编译出错。new_type 只要保证是类的指针或者引用,就不会编译出错。
可以用 typeid 在语义上实现 dynamic_cast :
template<typename T, typename T1>T1 *my_dynamic_cast(T *t){ if(typeid(t) == typeid(T1)){ return (T1*)t; } else{ return NULL; }}
二、typeid
函数原型:
type_info & typeid( object );
typeid 的主要作用是获得object变量的类型;它将返回一个type_info
对象的引用,type_info用于描述对象。如果object是对一个NULL指针的解引用,那么将抛出std::bad_typeid
异常。
当需要获得一个对象的类信息时,总是选择typeid
而不是 dynamic_cast
,因为typeid检测一个类型或者非强制转换的值时,只耗费常数时间。而 dynamic_cast 需要在运行时,对对象进行参数推导。
typeid 只对多态类型(该类至少包含一个virtual成员函数)有效,而且参数 object 是指针的解引用(typeid(*ptr) )或者对象引用( typeid(ref) )。因为只有包含虚函数的类指针(或者引用)才需要运行时检测,而其他的类型在编译时便能确定。
#include <iostream>#include <typeinfo> //for 'typeid' to workclass Person {public: // ... Person members ... virtual ~Person() {}};class Employee : public Person { // ... Employee members ...};int main () { Person person; Employee employee; Person *ptr = &employee; std::cout << typeid(person).name() << std::endl; // Person (statically known at compile-time) std::cout << typeid(employee).name() << std::endl; // Employee (statically known at compile-time) std::cout << typeid(ptr).name() << std::endl; // Person * (statically known at compile-time) std::cout << typeid(*ptr).name() << std::endl; // Employee (looked up dynamically at run-time // because it is the dereference of a // pointer to a polymorphic class)}
结果如下:
PersonEmployeePerson*Employee
- <C++> RTTI机制
- C++RTTI和反射机制
- 对于C+的RTTI机制的初步思考
- BCB中的RTTI机制
- RTTI的机制。
- BCB中的RTTI机制
- Java RTTI机制
- C++中的RTTI机制
- java的RTTI机制
- 浅析 RTTI机制
- C++实现机制RTTI
- C++中的RTTI机制
- RTTI机制详解
- C++ RTTI 机制
- RTTI机制与作用
- RTTI机制与作用
- RTTI 机制与作用
- C++中RTTI机制
- 第一个java程序——Dots and boxes游戏
- jquery-smartMenu 鼠标右键点击事件
- JDBC实例 Statement,PreparedStatement,CallableStatement三个方法的实例
- Android PDF开发:android-pdfview
- linux(centos6.5)安装开发环境jdk,tomcat.idea,git,maven,postgresql,rabbitmq
- C++ RTTI 机制
- 斐波那契数列 打印,求和
- 如何为Linux系统中的SSH添加双重认证
- OX09中的地址如何取
- 如何查看hadoop是32位还是64位
- Template的使用
- nyoj 90 整数划分【DFS】
- Android TextView中文字通过SpannableString来设置超链接、颜色、字体等属性
- C/C++标准输入输出与文件输入输出