C++ 多态4 RTTI

一、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

 

 

 


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值