博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
RTTI
阅读量:2382 次
发布时间:2019-05-10

本文共 3370 字,大约阅读时间需要 11 分钟。

RTTI,即 Run-Time Type Identification

在C++ 中,也称为 运行时类型识别

这里写图片描述
RTTI 的体现方式:
这里写图片描述
看如下实例

定义一个Flyable 类,其中有两个纯虚函数:takeoff() 和 land()

这里写图片描述
再定义一个Bird 类,它 public 的继承了 Flyable 类,并实现了 takeoff() 和 land(),并拥有自己独有的函数:foraging(),即觅食
这里写图片描述
再定义一个Plane 类,它 public 的继承了 Flyable 类,并实现了 takeoff() 和 land(),并拥有自己独有的函数:carry(),即 运输
这里写图片描述
在使用时:
这里写图片描述
假设有这样一个函数:doSomething(),其参数是 Flyable 的一个指针,在函数体中可以使用obj 去调用 takeoff() 和 land()。

再设想一下,如果能够对传入的指针再做进一步的判断,即:

  • 如果判断它是一个Bird 的对象指针,就能使用指针去调用 觅食 的函数

  • 如果判断它是一个Plane 的对象指针,就能使用指针去调用 运输 的函数

如果想要做到上述判断,就要使用RTTI 运行时类型识别

这里写图片描述
typeid(*obj).name() 可以获得当前 obj 指针指向的实际的对象类型,用cout 可以将其打印出来,再通过 if 语句进行比对,比对完成后,就可以将obj 通过 dynamic_cast 的方式将其转化成为 bird 的指针 。

转化时要注意:dynamic_cast 后面跟两个尖括号,中间写上要转化的目标类型。

总结:

关于 dynamic_cast 的注意事项:

  • 只能应用与指针和引用的转换,即只能转化为某一个类型的指针或某一个类型的引用,而不能是某类型本身

  • 要转化的类型中必须包含虚函数,如果没有虚函数,转换就会失败

  • 如果转换成功,返回子类的地址,如果转换失败,返回NULL

关于 typeid 的注意事项:

  • typeid 返回一个 type_info 的对象引用

  • 如果想通过基类的指针指向派生类的数据类型,基类就必须要带有虚函数,否则,在使用typeid 时,就只能返回定义时所使用的数据类型

  • typeid 只能获取对象的实际类型,即便这个类含有虚函数,也只能判断当前对象是基类还是派生类,而不能判断当前指针是基类还是派生类

type_info 中的内容:

class type_info{private:    type_info(const type_info&);    type_info& operator=(const type_info&);//type_info类的复制构造函数和赋值运算符是私有的。public:    virtual ~type_info();//析构函数    bool operator==(const type_info&)const;//在type_info类中重载了==运算符,该运算符可以比较两个对象的类型是否相等。    bool operator!=(const type_info&)const;//重载的!=运算符,以比较两个对象的类型是否不相等    const char* name()const;//使用得较多的成员函数name,该函数返回对象的类型的名字。前面使用的typeid(a).name()就调用了该成员函数    bool before(const type_info&);};

在上例中,typeid(*obj) 获取到的就是一个 type_info 的引用,通过该引用就能调用 type_info 中的 name() 函数。

type_info 中的 bool operator==(const type_info& rhs) const; 即运算符重载,通过它就可以进行两个type_info 对象的比对。

程序:

//Flyable.h#ifndef FLYABLE_H#define FLYABLE_H#include 
using namespace std;//接口类class Flyable{public: virtual void takeoff() = 0; virtual void land() = 0;};#endif
//Bird.h#ifndef BIRD_H#define BIRD_H#include"Flyable.h"class Bird:public Flyable{public:    void foraging();    virtual void takeoff();    virtual void land();};#endif
//Bird.cpp#include"Bird.h"void Bird::foraging(){    cout << "Bird--foraging" << endl;}void Bird::takeoff(){    cout << "Bird--takeoff" << endl;}void Bird::land(){    cout << "Bird--land" << endl;}
//Plane.h#ifndef PLANE_H#define PLANE_H#include"Flyable.h"class Plane:public Flyable{public:    void carry();    virtual void takeoff();    virtual void land();};#endif
//Plane.cpp#include"Plane.h"void Plane::carry(){    cout << "Plane--carry" << endl;}void Plane::takeoff(){    cout << "Plane--takeoff" << endl;}void Plane::land(){    cout << "Plane--land" << endl;}
//main.cpp#include"Bird.h"#include"Plane.h"void doSomething(Flyable *obj);int main(void){    Bird b;    Plane p;    doSomething(&b);    cout << endl;    doSomething(&p);    //对typeid的验证    /*cout << endl;    int i = 0;    cout << typeid(i).name() << endl;    Flyable *t = new Bird();    cout << typeid(t).name() << endl;    cout << typeid(*t).name() << endl;*/    system("pause");    return 0;}void doSomething(Flyable *obj){    //这里打印的是数据类型, 传入的不是obj指针而是对象*obj    cout << typeid(*obj).name() << endl;    obj->takeoff();    //两个type_info对象的比对运算符重载    if (typeid(*obj) == typeid(Bird))    {        //转化为Bird的指针        Bird *bird = dynamic_cast
(obj); bird->foraging(); } if (typeid(*obj)==typeid(Plane)) { Plane *plane = dynamic_cast
(obj); plane->carry(); } obj->land();}

运行一览:

这里写图片描述

此文章转载自:

你可能感兴趣的文章
Python爬虫入门,8个常用爬虫技巧盘点
查看>>
Python轻松查看微信撤回消息,秘密无处可藏
查看>>
国外Python黑客技术,攻击自动化玩得真6
查看>>
最后悔的是遇见了Python!
查看>>
前端程序员市场分析:前面是火海,后面是刀山,走还是不走?
查看>>
做程序员一般都需要什么学历?大厂招不招低学历?你想知道的都在这里了
查看>>
零基础html5网站开发学习步骤方法
查看>>
程序员真实生活曝光,蹦迪也带着电脑,网友解释:这样才有安全感!
查看>>
CSS的23个垂直居中技巧,你都学会了吗?
查看>>
黑客攻击用的最短代码大揭秘,颠覆你的世界观!
查看>>
零基础的自学前端之路,当年的入坑之旅
查看>>
新手程序员?教你解决办法!基础都掌握了,动手敲代码就一脸懵逼
查看>>
程序员快速进阶学习到底要看书还是要看视频?
查看>>
web游戏框架哪家强?国内外精选优质框架分析及注意事项
查看>>
各行业都爱用什么编程语言开发?
查看>>
css3实现ps蒙版效果以及动画,炫酷吊炸天!
查看>>
程序员休息时间接私活遭公司辞退,不明觉厉?
查看>>
CSS 、JS实现浪漫流星雨动画
查看>>
花4万学代码,工资却只有5千,这个程序员做的..
查看>>
新手网站建设指南(2)
查看>>