1. 一、定义RTTIRun Time Type Identification ,执行时类型识别:指程序可以使用基类的指针或引用来检索其所指对象的实际派生类型。
  2. 二、使用方式C++中有两个操作符提供RTTI
  3. 1typeid 操作符:返回指针或引用所指对象的实际类型。
  4. 2dynamic_cast 操作符:将基类类型的指针或引用安全地转换为派生类型的指针和引用。
  5.  :此二操作符仅仅为带有一个或多个虚函数的类返回动态类型信息----即在执行时执行RTTI操作符;对于其它类型则返回静态类型的信息---即在编译时计算RTTI操作符。
  6. 三、详细介绍
  7. 1typeid
  8. 头文件:# include<typeinfo>
  9. 语法--两种形式:typeid (type) typeid (expression)即随意表达式或类型名。
  10.  
  11. 常见的用途:比較两个表达式的类型。或者将表达式的类型与特定类型相比較。
  12. typeid返回类型const type_info&
  13. 详细定义例如以下:
    1. class type_info{
    1. public:
    1. virtul ~type_info();
    1. bool operator == (const type_info&rhs)const;
    1. bool operator != (const type_info&rhs)const;
    1. bool before(const type_info&rhs)const;
    1. const char* name()const;
    1. private:
    1. type_info(const type_info& rhs);
    1. type_info& operator=(const type_info& rhs);
    1. }
  1.  
  1. 接口说明
  2. operator ==和operator!=:比較操作符。返回两个类型是否为(或不为)同一类型(注:基类和派生类不为同一类型!
  3.  
  4. )。
  5. before:若在类型排序中。该类型先于rhs的类型则返回true
  6.  
  7. name:返回类型相应的名字(详细所用的值,依赖于详细编译器)(以\0结束的字符串)。
  8. 注意type_info类的默认构造函数和复制构造函数以及赋值操作符都定义为private,故不能定义或复制type_info类型的对象。程序中创建type_info对象的唯一方法是使用typeid操作符。
  9.  
  10. 样例:(来源
    1. #include <iostream>
    1. #include <typeinfo>
    1. using namespace std;
    1. struct Base {};
    1. struct Derived : Base {};
    1. struct Poly_Base {virtual void Member(){}};
    1. struct Poly_Derived: Poly_Base {};
    1. int main() {
    1. int a;
    1. int * pa;
    1. cout << "int is: " << typeid(int).name() << endl;
    1. cout << "  a is: " << typeid(a).name() << endl;
    1. cout << " pa is: " << typeid(pa).name() << endl;
    1. cout << "*pa is: " << typeid(*pa).name() << endl << endl;
    1. Derived derived;
    1. Base* pbase = &derived;
    1. cout << "derived is: " << typeid(derived).name() << endl;
    1. cout << "*pbase is: " << typeid(*pbase).name() << endl;
    1. cout << "same type?
    1. ";
    1. cout << ( typeid(derived)==typeid(*pbase) ) << endl << endl;
    1. Poly_Derived polyderived;
    1. Poly_Base* ppolybase = &polyderived;
    1. cout << "polyderived is: " << typeid(polyderived).name() << endl;
    1. cout << "*ppolybase is: " << typeid(*ppolybase).name() << endl;
    1. cout << "same type?
    1. ";
    1. cout << ( typeid(polyderived)==typeid(*ppolybase) ) << endl << endl;
    1. return 0;
    1. }
  11.  
  1. 执行结果:(尝试了两个编译环境:g++ (GCC) 4.4.6 20120305 (Red Hat 4.4.6-4) VC6.0
  2. G++结果:
  3.  
  4. VC6.0结果:
  5.  
  6. 注:尽管 typeid(*ppolybase)返回派生类类型。可是 typeid(ppolybase)依然是返回基类指针类型。
  7.  
  8. 同理,引用相似:假设r是引用,typeid(r)返回派生类类型,typeid(&r)则依然返回基类类型。
  1. 注意到:两个编译环境的执行结果不一样---即typeid在不同编译环境下返回的结果是不一致的!
  2.  
  3. 为什么会这样呢?
  4. 由于:标准C++规定,type_info类的确切定义随编译器而变化,仅仅要保证全部的实现提供以上的基本操作即可(见类定义)。即详细实现细节。各编译器厂商可自行决定。
  5. 注:在VC6.0执行时,记得把编译选项加上“/GR ,否则编译时会出现Warningproject--设置--C/C++---project选项)。
  6.  
  7. 由于VC6.0默认不开启RTTI
  8.  
  9. 2dynamic_cast
  10. 语法形式:dynamic_cast<T>(v) ,将对象 v 转换为类型T的对象。
  11. 前提:v 要么为指向其派生类对象的基类指针,要么为引用其派生类对象的基类对象。否则。v 返回NULL(为指针时)或抛出std::bad_cast(在头文件<typeinfo>中定义)异常(为引用类型时);而T为所期望的派生类指针类型或派生类引用类型。
  12.  
  13. 且。v指向的基类里必须包括虚函数,即多态类型。否则编译出错。
  14.  
  15. 经常使用写法:
  16. IPoly_Derived* derivedPtr = dynamic_cast<Poly_Derived*>(ppolybase);//转换为指向Poly_Derived 型的指针,失败返回NULL;
  17. IIPoly_Derived& derivedRef = dynamic_cast<Poly_Derived&>(polyderived); //转换为Poly_Derived 引用,失败时抛出bad_cast异常。
  18. 详细见样例:
    1. #include <iostream>
    1. #include <typeinfo>
    1. using namespace std;
    1. struct Poly_Base {virtual void Member(){}};
    1. struct Poly_Derived: Poly_Base {};
    1. int main() {
    1. Poly_Derived polyderived;
    1. Poly_Base* ppolybase = &polyderived;
    1. Poly_Base& rpolybase = polyderived;
    1. if(Poly_Derived* derivedPtr = dynamic_cast<Poly_Derived*>(ppolybase))//base pointer
    1. {
    1. cout<<"dynamic_cast pointer success."<<endl;
    1. }
    1. else
    1. {
    1. cout<<"dynamic_cast pointer fail!"<<endl;
    1. }
    1. try{
    1. const Poly_Derived& derivedRef = dynamic_cast<const Poly_Derived&>(rpolybase);
    1. cout<<"dynamic_cast reference success."<<endl;
    1. }catch(bad_cast){
    1. cout<<"dynamic_cast reference fail."<<endl;
    1. }
    1. cout <<"same type? ";
    1. cout << ( typeid(rpolybase)==typeid(*ppolybase) ) << endl;
    1. return 0;
    1. }
  19.  

执行结果:

原文链接: http://blog.csdn.net/heyabo/article/details/8348624

參考文章:

1.  http://www.cplusplus.com/reference/typeinfo/type_info/
2.  http://en.cppreference.com/w/cpp/language/typeid
3.  http://stackoverflow.com/questions/1986418/typeid-and-typeof-in-c
4.  http://renhl252.blog.163.com/blog/static/2122100720098229281284/

C++ RTTI介绍的更多相关文章

  1. c++之RTTI介绍

    本文介绍c++的RTTI的基本用法,并初步研究RTTI的实现原理. 1. 什么是RTTI RTTI即运行时类型识别(runtime type identification),用于判断指针或引用所绑定对 ...

  2. RTTI

    RTTI(Run-Time Type Identification,通过运行时类型识别)程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型.   编辑本段RTTI介绍 RTTI提 ...

  3. Delphi 类的类 class of 用法

    http://blog.csdn.net/blue_morning/article/details/8815609 Delphi 类的类 class of 用法   这个概念本来在一个关于Delphi ...

  4. Delphi 类引用 Class Reference 元类 MetaClass 用法

    delphi中类引用的使用实例 类引用类引用(Class Reference)是一种数据类型,有时又称为元类(MetaClass),是类的类型的引用.类引用的定义形式如下: class of type ...

  5. Java系列笔记(2) - Java RTTI和反射机制

    目录 前言 传统的RTTI 反射 反射的实现方式 反射的性能 反射与设计模式 前言 并不是所有的Class都能在编译时明确,因此在某些情况下需要在运行时再发现和确定类型信息(比如:基于构建编程,),这 ...

  6. RTTI (Run-Time Type Identification,通过运行时类型识别) 转

    参考一: RTTI(Run-Time Type Identification,通过运行时类型识别)程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型.   RTTI提供了以下两个 ...

  7. C++中的RTTI机制解析

    RTTI RTTI概念 RTTI(Run Time Type Identification)即通过运行时类型识别,程序能够使用基类的指针或引用来检查着这些指针或引用所指的对象的实际派生类型. RTTI ...

  8. C++ RTTI

    一.定义:RTTI:Run Time Type Identification ,运行时类型识别:指程序能够使用基类的指针或引用来检索其所指对象的实际派生类型.二.使用方式:C++中有两个操作符提供RT ...

  9. C++重载(主要介绍使用友元函数重载)

    重载限制 多数C++运算符都可以用下面的方式重载.重载的运算符不必是成员函数,但必须至少有一个操作数是用户自定义的类型.下面详细介绍C++对用户定义的运算符重载的限制. 1 重载后的运算符必须至少有一 ...

随机推荐

  1. eclipse自动为变量生成Get/Set函数

    启动Eclipse,打开demo工程.如图:   假定为成员变量test生成Get/Set函数. 光标定位到该成员变量,如图:   右键选择“source”-“Generate Getters and ...

  2. mysql 修改表的字段

    修改一个表的字段 ALTER TABLE `member` CHANGE `memberid` `memberid` bigint unsigned; 修改含有外键的字段 -- 执行 begin 到 ...

  3. 不能局部安装webpack的解决方法

    npm ERR! code ENOSELFnpm ERR! Refusing to install package with name "webpack" under a pack ...

  4. 【计算机网络】2.5 DNS:因特网的目录服务

    第二章第五节 因特网的目录服务 DNS(域名系统)提供了一种能运行主机名到IP地址转换的因特网目录服务:一方面,他让人能够记住如taobao.com这样的主机别名:另一方面,他提供给路由器可理解的IP ...

  5. 为什么java String是固定的 为什么字符串是不可变的

    String类不可变的好处 String是所有语言中最常用的一个类.我们知道在Java中,String是不可变的.final的.Java在运行时也保存了一个字符串池(String pool),这使得S ...

  6. 《BUG创造队》第五次作业:项目需求分析改进与系统设计

    项目 内容 这个作业属于哪个课程 2016级软件工程 这个作业的要求在哪里 实验九 团队作业5-团队项目需求改进与系统设计 团队名称 BUG创造队 作业学习目标 1.编写完整<软件需求规格说明书 ...

  7. Android ListView setEmptyView

    http://my.eoe.cn/yaming/archive/879.html 1 当我们使用ListView或GridView的时候,当列表为空的时候,我们需要一个特殊的View来提示用户操作,于 ...

  8. [Python3网络爬虫开发实战] 2.5-代理的基本原理

    我们在做爬虫的过程中经常会遇到这样的情况,最初爬虫正常运行,正常抓取数据,一切看起来都是那么美好,然而一杯茶的功夫可能就会出现错误,比如403 Forbidden,这时候打开网页一看,可能会看到“您的 ...

  9. c++基础_01字串

    #include <iostream> using namespace std; int main(){ for(int a=0;a<=1;a++){ for(int b=0;b&l ...

  10. 添物不花钱学JavaEE(基础篇)-XML

    XML(Extensible Markup Language) XML在日常工作中经常用到,必须有个了解,不过认识一下即可,不要太浪费时间.实际用到 参考图书 <XML入门经典>大而全,不 ...