首页 > 代码库 > c++中RTTI
c++中RTTI
RTTI 是“Runtime Type Information”的缩写,意思是:运行时类型信息。它提供了运行时确定对象类型的方法。本文将简略介绍 RTTI 的一些背景知识、描述 RTTI 的概念,并通过具体例子和代码介绍什么时候使用以及如何使用 RTTI;本文还将详细描述两个重要的 RTTI 运算符的使用方法,它们是 typeid 和 dynamic_cast。如何确定对象的动态类型呢?答案是使用内建的 RTTI 中的运算符:typeid 和 dynamic_cast。
typeid的主要作用就是让用户知道当前的变量是什么类型的,对于我们自定义的结构体和类,tpyeid都能支持。
typeid是C++的关键字之一,等同于sizeof这类的操作符。typeid操作符的返回结果是名为type_info的标准库类型的对象的引用,它的表达式有下图两种形式。
如果表达式的类型是类类型且至少包含有一个虚函数,则typeid操作符返回表达式的动态类型,需要在运行时计算;否则,typeid操作符返回表达式的静态类型,在编译时就可以计算。ISO C++标准并没有确切定义type_info,它的确切定义编译器相关的,但是标准却规定了其实现必需提供如下四种操作(在之后的章节中我会来分析type_info类文件的源码):
t1 == t2 | 如果两个对象t1和t2类型相同,则返回true;否则返回false |
t1 != t2 | 如果两个对象t1和t2类型不同,则返回true;否则返回false |
t.name() | 返回类型的C-style字符串,类型名字用系统相关的方法产生 |
t1.before(t2) | 返回指出t1是否出现在t2之前的bool值 |
#include <iostream>
using namespace std;
class Base {};
class Derived: public Base {};
int main()
{
Base b, *pb;
pb = NULL;
Derived d;
cout << typeid(int).name() << endl
<< typeid(unsigned).name() << endl
<< typeid(long).name() << endl
<< typeid(unsigned long).name() << endl
<< typeid(char).name() << endl
<< typeid(unsigned char).name() << endl
<< typeid(float).name() << endl
<< typeid(double).name() << endl
<< typeid(string).name() << endl
<< typeid(Base).name() << endl
<< typeid(b).name()<<endl
<< typeid(pb).name()<<endl
<< typeid(Derived).name() << endl
<< typeid(d).name()<<endl
<< typeid(type_info).name() << endl;
return 0;
}
运行结果:
dynamic_cast 操作符,将基类的指针或引用安全的转换为派生类的指针或引用。
1. 原理:将一个基类对象指针(或引用)cast (抛)到继承类指针,dynamic_cast 会根据基类指针是否真正指向继承类指针来做相应处理。
2. 返回值:对指针进行dynamic_cast,失败返回null,成功返回正常cast后的对象指针;对引用进行dynamic_cast,失败抛出一个异常,成功返回正常cast后的对象引用。
3. 注意:dynamic_cast在将父类cast到子类时,父类必须要有虚函数。
在c++中使用dynamic_cast进行类型转换属于向下类型,即将基类类型转换为派生类类型,向上类型转换编译器可以自动完成。
下面的代码说明了C++中RTTI运行机制。
#include <iostream> #include <typeinfo> using namespace std; class base { public: virtual void funA() {cout<<"Base "<<endl;} }; class derived : public base { public: virtual void funB() { cout<<"derived "<<endl;} }; void funcC(base* p) { derived* dp=dynamic_cast<derived*>(p); if(dp!=NULL) dp->funB(); else p->funA(); } void funcD(base* p) { derived* dp=NULL; if(typeid(*p)==typeid(derived)) { dp=static_cast<derived*>(p); dp->funB(); } else p->funA(); } int main() { base *cp=new derived;//向上类型转换,系统自动完成,指针cp指向derived中继承base部分 cout<<typeid(cp).name()<<endl;//class base* cout<<typeid(*cp).name()<<endl;//class derived funcD(cp); //typeid(*cp)==typeid(derived),使用static_cast<derived*>(cp)也可以将基类转换为派生类,是在编译时完成,而dynamic_cast是在运行时处理的 funcC(cp);//采用dynamic_cast完成基类到派生类的转换,转换成功 base* dp=new base; funcC(dp);//基类指针指向基类,此时采用dynamic_cast完成基类到派生类的转换失败。
funcD(dp); return 0; }
运行结果为:
class base* class derived class derived class derived class base class base
注意:基类指针或引用指向派生类对象的情况,此时转换才有意义。 否则转换就不能成功,如上面的funcC(dp)函数中derived* dp=dynamic_cast<derived*>(dp)就失败了,返回NULL
c++中RTTI
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。