多態(Polymorphism)按字面的意思就是“多種狀態”。在面向對象的語言中,接口的多種不同的實現方式即為多態。引用Charlie Calverts對多態的描述——多態性是允許你將基類設置成為和一個或更多的他的子類相等的技術,賦值之后,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作。
RTTI 是“Runtime Type Information”的縮寫,意思是:運行時類型信息。它提供了運行時確定對象類型的方法。本文將簡略介紹 RTTI 的一些背景知識、描述 RTTI 的概念,並通過具體例子和代碼介紹什么時候使用以及如何使用 RTTI;
本文還將詳細描述兩個重要的 RTTI 運算符的使用方法,它們是 typeid 和 dynamic_cast。
首先讓我們來設計幾個層次類:(這里盡可能的簡單)
基類:
class Human
{
};
class Chinese : public Human
{
};
class Japanese : public Human
{
};
/////////////////////////////////////////////////////////
使用場景:有個函數
void Kill(Human *pHuman)
{
if(typeid(*pHuman) == typeid(Japanese))
{
//kill
}
else if(typeid(*pHuman) == typeid(Chinese))
{
// not kill
}
}
這樣在傳入 Japanese 的時候就會Kill了。
typeid的name函數用於查看對象類型
例如:Chinese human;
cout << human is << typeid(human).name() << endl;
會輸出: human is Class Chinese
dynamic_cast,這個運算符用於多態編程中保證在運行時發生正確的轉換(即編譯器無法驗證是否發生正確的轉換)。dynamic_cast 常用於從多態編程基類指針向派生類指針的向下類型轉換。它有兩個參數:一個是類型名;另一個是多態對象的指針或引用。其功能是在運行時將對象強制轉換為目標類型並返回布爾型結果。
Kill 第二版
void Kill(Human *pHuman)
{
if(dynamic_cast<Japanese*>(pHuman))
{
//kill
}
else
{
// not kill
}
}
///////////////////////////////////////////
雖然使用 dynamic_cast 確實很好地解決了我們的問題,但也需要我們付出代價,那就是與 typeid 相比,dynamic_cast 不是一個常量時間的操作。為了確定是否能完成強制類型轉換,dynamic_cast`必須在運行時進行一些轉換細節操作。因此在使用 dynamic_cast 操作時,應該權衡對性能的影響.
RTTI具體使用場景:
假設你正在開發一個基於圖形用戶界面(GUI)的文件管理器,每個文件都可以以圖標方式顯示。當鼠標移到圖標上並單擊右鍵時,文件管理器打開一個菜單,每個文件除了共同的菜單項,不同的文件類型還有不同的菜單項。如:共同的菜單項有“打開”“拷貝”、和“粘貼”,此外,還有一些針對特殊文件的專門操作。比如,文本文件會有“編輯”操作,而多媒體文件則會有“播放”菜單。為了使用 RTTI 來動態定制菜單,文件管理器必須偵測每個文件的動態類型。利用 運算符 typeid 可以獲取與某個對象關聯的運行時類型信息。typeid 有一個參數,傳遞對象或類型名。因此,為了確定 x 的動態類型是不是Y,可以用表達式:typeid(x) == typeid(Y)實現:#include <typeinfo> // typeid 需要的頭文件
void menu::build(const File * pfile)
{
if (typeid(*pfile)==typeid(TextFile))
{
add_option("edit");
}
else if (typeid(*pfile)==typeid(MediaFile))
{
add_option("play");
}
}
----------------努力向學 蔚為國用-----------------