一、RTTI
RTTI是Runtime Type Identification的缩写,意思是运行时类型识别。
C++引入这个机制是为了让程序在运行时能根据基类的指针或引用来获得该指针或引用所指的对象的实际类型。但是现在RTTI的类型识别已经不限于此了,它还能通过typeid操作符识别出所有的基本类型(int,指针等)的变量对应的类型。
C++通过以下的两个操作提供RTTI:
(1)typeid运算符,该运算符返回其表达式或类型名的实际类型。
(2)dynamic_cast运算符,该运算符将基类的指针或引用安全地转换为派生类类型的指针或引用。
RTTI必须建立在虚函数的基础上,否则无需RTTI技术
RTTI技术可以通过父类指针识别其所指向对象的真实数据类型
1、typeid运算符
typeid运算符,后接一个类型名或一个表达式,该运算符返回一个类型为std::tpeinf的对象的const引用。
typeid注意事项:
- type_id返回一个type_info对象的引用
- 如果想通过基类的指针获得派生类的数据类型,基类必须带有虚函数
- 只能获取对象的实际类型
2、dynamic_cast运算符
把一个基类类型的指针或引用转换至继承架构的末端某一个派生类类型的指针或引用被称为向下转型(downcast)。dynamic_cast运算符的作用是安全而有效地进行向下转型。
dynamic_cast注意事项:
- 只能应用于指针和引用的转换
- 要转换的类型中必须包含虚函数
- 转换成功返回子类的地址,失败返回NULL
二、代码示例
RTTI(运行时类型识别)
1、Flyable类,成员函数:takeoff、land
2、Plane类,成员函数:takeoff、land、carry
3、Bird类,成员函数:takeoff、land、foraging
4、全局函数doSomething(Flyable *obj)
Flyable.h
#ifndef FLYABLE_H
#define FLYABLE_H
#include<iostream>
#include<string>
using namespace std;
class Flyable//接口类(仅有纯虚函数)
{
public:
virtual void takeoff() = 0;
virtual void land() = 0;
};
#endif
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;
}
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;
}
main.cpp
#include"Plane.h"
#include"Bird.h"
/*****************
RTTI(运行时类型识别)
1、Flyable类,成员函数:takeoff、land
2、Plane类,成员函数:takeoff、land、carry
3、Bird类,成员函数:takeoff、land、foraging
4、全局函数doSomething(Flyable *obj)
******************/
void doSomething(Flyable *obj)
{
cout<<typeid(*obj).name()<<endl;//打印所传入的对象 指针的类型,obj这个指针所传入的对象
obj->takeoff();
if(typeid(*obj) == typeid(Bird))
{
Bird *bird = dynamic_cast<Bird*>(obj);//将obj这个指针通过dynamic_cast转换成Bird*,并且将这个Bird*赋值给一个新的指针bird
bird->foraging();
}
if(typeid(*obj) == typeid(Plane))
{
Plane *plane = dynamic_cast<Plane*>(obj);
plane->carry();
}
obj->land();
}
int main()
{
Bird b;
doSomething(&b);
Flyable *p = new Bird();
cout<<typeid(p).name()<<endl;
cout<<typeid(*p).name()<<endl;
return 0;
}
运行结果:
其他有关RTTI博客:
C++对象模型之RTTI的实现原理https://blog.csdn.net/ljianhui/article/details/46487951