標籤:c++ 運行時類型識別 typeid dynamic_cast type_info
特殊工具與技術--運行時類型識別[續]
三.RTTI的使用
當比較兩個衍生類別對象的時候,我們希望比較可能特定於衍生類別的資料成員.如果形參是基類引用,就只能比較基類中出現的成員,我們不能訪問在衍生類別中但不在基類中出現的成員.
因此我們可以使用RTTI,在試圖比較不同類型的對象時返回假(false)。
我們將定義單個相等操作符。每個類定義一個虛函數 equal,該函數首先將運算元強制轉換為正確的類型。如果轉換成功,就進行真正的比較;如果轉換失敗,equal 操作就返回 false。
1.類層次
class Base{ friend bool operator==(const Base &,const Base &);public: // interface member for baseprivate: virtual bool equal(const Base &) const;};class Derived : public Base{ friend bool operator==(const Derived &,const Derived &);public: // interface member for baseprivate: virtual bool equal(const Base &) const;};
2.類型敏感的相等操作符
bool operator==(const Base &lhs,const Base &rhs){ return typeid(lhs) == typeid(rhs) && lhs.equal(rhs);}
3.虛函數equal
層次中的每個類都必須定義自己的equal版本.衍生類別中的equal函數將以相同的方式開始:將實參強制轉換成為類本身的資料類型.
bool Derived::equal(const Base &rhs) const{ //必須將其轉換成為指標類型,其原因請參考上一篇C++ Primer部落格 if (const Derived *dp = dynamic_cast<const Derived *>(&rhs)) { // compare two Derived objects and return result } return false;}
4.基類equal函數
bool Base::equal(const Base &rhs) const{ // compare two Base objects and return result}
使用形參之前不必強制轉換,*this和形參都是Base對象,所以對形參類型也定義了該對象的所有操作.
四.type_info類
type_info支援的操作 |
t1 == t2 |
如果兩個對象 t1 和 t2 類型相同,就返回 true;否則,返回false |
t1 != t2 |
t1 != t2 如果兩個對象 t1 和 t2 類型不同,就返回 true;否則,返回false |
t.name() |
t.name() 返回 C 風格字串,這是類型名字的可顯示版本。類型名字用系統相關的方法產生 |
t1.before(t2) |
返回指出 t1 是否出現在 t2 之前的 bool 值。before 強制的次序與編譯器有關 |
因為打算作基類使用,type_info 類也提供公用虛解構函式。如果編譯器想要提供附加的類型資訊,應該在 type_info 的衍生類別中進行。
預設建構函式和複製建構函式以及賦值操作符都定義為 private,所以不能定義或複製 type_info 類型的對象。 程式中建立 type_info 對象的唯一方法是使用 typeid 操作符。
name 函數為 type_info 對象所表示的類型的名字返回 C 風格字串。給定類型所用的值取決於編譯器,具體來說,無須與程式中使用的類型名字匹配。對 name 傳回值的唯一保證是,它為每個類型返回唯一的字串。雖然如此,仍可以使用 name 成員來顯示 type_info 對象的名字:
int iobj; cout << typeid(iobj).name() << endl; cout << typeid(8.16).name() << endl; cout << typeid(std::string).name() << endl; cout << typeid(Base).name() << endl; cout << typeid(Derived).name() << endl;
G++編譯器顯示:
注:name返回的格式和值隨編譯器而變化.type_info類隨編譯器而變.一些編譯器提供的附加的成員函數,那些函數提供關於程式中所用類型的附加資訊.
//P653 習題18.20class A {};class B : public A {};class C : public B {};int main(){ A *pa = new C(); cout << typeid(*pa).name() << endl; //1A cout << typeid(pa).name() << endl; //P1A C cobj; A &ra = cobj; cout << typeid(&ra).name() << endl; //P1A cout << typeid(ra).name() << endl; //1A B *px = new B; A &raTest = *px; cout << typeid(raTest).name() << endl; //1A}