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的學習筆記都寫完了,也可能有理解錯誤的地方,在這裏記錄一下.方便今後使用的時候來閱讀.


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