RTTI学习笔记

翻看C++的书,对RTTI的讲解都很困惑,"你知道你的对象是哪个类吗?","RTTI常用于调试和数据库程序"对这些讲解本来就对"运行时类型识别"这个词很迷惑的我来说就更迷糊了.我认为还是C++ PRIMER这本书讲的很好.一开始就给出了答案:RTTI允许"用指向基类或引用来操纵对象"的程序能够获取到"这些指针所指对象"的实际派生类型.这句话虽然很苦涩难懂,但讲的再清楚不过了.RTTI就是对多态的类型转换的反操作,我讲的可能不是很标准.没有人家的讲的话那么严谨,呵呵.对RTTI基本使用dynamic_cast 和 typeid两种操作方式.


第一:dynamic_cast操作.无论怎么看书我对这个操作都很迷茫,越看越觉得有点懂还有点不懂.后来我仔细的思考后感觉dynamic_cast使用必须满足一个条件,就是所操纵的对象必须有一个虚函数.我知道C++中的对象实际上就是指向内存中的一些变量,而虚函数就是变量多一个函数指针.这样就得到答案:dynamic_cast实际上就是判断两个对象的虚函数指针是不是指向同一个函数地址.那么dynamic_cast就是一种强制类型转换操作,它提供一种安全的工作方式,可以将父类转换成子类.

dynamic_cast有指针判断和引用判断两种,下面用C++ PRIMER上的例子进行举例:

class employee{
public:
virtual int salary();
};
class programmer:public employee{
public:
int salary();
int bonus();
};
//使用指针
void company::payroll(employee *pe){
if (programmer *pm=dynamic_cast<programmer*>(pe))
{
pm->bonus();
}
}
//使用引用
void company::payroll(employee &re){
try
{
programmer &rm=dynamic_cast<programmer &>(re);
rm.bonus();
}
catch (std::bad_cast)
{
}
}


第二:typeid操作.对typeid的理解好象容易的多,它返回type_info这个类,根据书上的讲解,type_info这个类是编译器实现的,这个类根据不同的编译器会有不同的支持,包括比较两个对象,对象的类名,还会有函数清单,类型对象的内存布局等.那比较两个对象就可以用这个类实现更强大的功能.对于type_info这个类的使用我有很多疑问,它是跟类一起创建的?还是跟对象一起创建的?如果保存对象是不是也要保存thpe_info这个类对象呢?可是这些书上都没有答案。毕竟这是一本初级的书,可能需要到高级或实际编程中获得答案。type_info的构造函数是私有的,这个类必须由typeid才创建,那就说明typeid是type_info类的一个友元.但让我非常迷惑的是typeid写法.还是以C++ PRIMER上的例子的来说明.

#include <typeinfo>
employee *pe =new manager;
employee re=*pe;
//这里为什么不能用在RTTI呢?
if(typeid(pe)==typeid(employee*))//true
if(typeid(pe)==typeid(manager*))//false
if(typeid(pe)==typeid(employee))//false
if(typeid(pe)==typeid(manager))//false
//这个还好理解吧
if(typeid(*pe)==typeid(manager))//true
if(typeid(*pe)==typeid(employee))//false
//这个也可以
if(typeid(re)==typeid(manager))//true
if(typeid(re)==typeid(employee))//false
//这里又不行了.
if(typeid(&re)==typeid(employee*))//true
if (typeid(&re)==typeid(manager*))//false


我对这样的写法很难理解,到底哪个写法是正确的呢?经过我仔细的阅读才明白原来typeid不但可以用在RTTI上.还可以用在识别各种类,变量和常量上.用于识别它们的数据类型.比如C++ PRIMER上的例子:


int i;
cout<<typeid(i).name()<<endl;//打印:int
cout<<typeid(8.16).name()<<endl;//打印:double
class Bass{/*没有虚函数*/};
class Derived :public Bass{/*没有虚函数*/};
Derived dobj;
Bass *pb=&dobj;
cout<<typeid(*pb).name()<<endl;//打印:Base


那么怎么写才可以用在RTTI的类型转换上呢?那就是表达式是一个类的类型.而不是一个类的指针.


上面对RTTI的学习笔记都写完了,也可能有理解错误的地方,在这里记录一下.方便今后使用的时候来阅读.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章