RTTI: dynamic_cast typeid
dynamic_cast:將基類類型的指針向派生類指針安全轉換。多用于下行轉換。上行轉換時,和static_cast是一樣的。C++類型轉換看這里。而const_cast用來修改類型的const或volatile屬性。。。下面主要說多態下的RTTI:
使用條件:
基類應有虛函數。
編譯器需啟用Runtime Type Information/Identification(RTTI),運行時類型信息。VS下在項目屬性頁下啟用,如下,選?是: (VS2013測試:默認的留空不選也能正常使用dynamic_cast)
結果:
對指針進行dynamic_cast,失敗返回null,成功返回正常cast后的對象指針; //首選
對引用進行dynamic_cast,失敗拋出一個異常std::bad_cast,成功返回正常cast后的對象引用。
用處:一般用在多態中,即基類的指針或引用指向派生類對象時,進行安全的向下轉換。
多態的基本例子如下:
可看到,由于基類指針實際指向派生類實例,所以實際調用的是派生類里的vFoo()函數。
但嘗試?pBase->Other();//編譯出錯?,雖然pBase指向派生類實例,但指針本身的類型卻決定了它所能調用的函數范圍。
強制轉換下呢:?((Derived*)pBase)->Other();//"Derived::Other()"?,成功了。
但如果這樣呢:
Base *pBase = new Base; ((Derived*)pBase)->Other();仍然成功了,正確輸出。實際Other函數可以直接使用Derived::Other()來調用的,因為函數里沒交互數據成員。但如果交互了呢:
//Derived類里: public:int a = 6;//C++11void Other(){cout << a << endl;//隨機數字,如73756547a = 100;} };//main里 Base *pBase = new Base; ((Derived*)pBase)->Other();運行后竟仍然成功了。但從輸出的a是隨機數字可以看出int a =6;并沒有執行過,因為new的是Base實例。這里我們雖依然運行成功,但從程序上看,這是不對的。如果Derived類封裝的更復雜(比如在構造函數里new, Other里delete),可能肯定運行時會崩潰!所以c語言形式的強制轉換在此種情況下是不安全的。
可能問,為什么一定要調用Other函數呢,如果一定要在使用多態時調用它,在基類里添加Other函數并聲明它為虛函數不就行了。是的,這樣可以。但有時,比如我使用了一個第三方庫(封裝到lib里,只提供了它的頭文件),我在從它繼承的派生類中添加了新函數,并想在多態下使用。此時是不可能在第三方庫里添加虛函數的,因為庫不能重新編譯。這時就需要安全的類型轉換了。dynamic_cast就可以在此種情況下起作用:
對基類指針,不屬于某個派生類實例將返回null,這樣可用來判斷類型:
?
typeid:
http://www.cppblog.com/smagle/archive/2010/05/14/115286.aspx這篇寫的很好,我就不怎么寫了。。。直接貼它的幾個例子吧
需要注意(仍根據上文例子):
Base *pBase = new Derived;
cout << typeid(pBase).name() << endl; //class Base* ? 雖然基類有虛函數且指針指向派生類對象,但仍輸出指針類型本身
cout << typeid(*pBase).name() << endl;//class Derived
Base &rD = *pBase;//class Derived ? //注意,引用和指針結果不同
//所以typeid能對含虛函數的類類型(對象本身或引用)判斷出其指向的對象的類型信息,對指針無用。
例子:
#include <iostream> using namespace std;class Base { }; class Derived: public Base { };void foo() { } 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 << endl//函數類型和函數指針也可以<< typeid(void (*)(int, int)).name() << endl<< typeid(foo).name() << endl << endl<< typeid(Base).name() << endl<< typeid(b).name()<<endl<< typeid(pb).name()<<endl //雖然指向NULL,但本身類型是Base *<< typeid(Derived).name() << endl<< typeid(d).name()<<endl<< typeid(type_info).name() << endl;return 0; } 基本類型與一般類?
#include <iostream> using namespace std;class Base { public:virtual void foo(){}virtual ~Base(){} }; class Derived: public Base { };int main() {Base *pd = new Derived;cout << typeid(pd).name() << endl //class Base *<< typeid(*pd).name() << endl;Base &rD = *pd;cout << typeid(rD).name() << endl;//雖無法從指針本身上判斷,但可對其解引用if(typeid(Derived) == typeid(*pd))cout << "類型相同" << endl;elsecout << "類型不同" << endl;delete pd;return 0; }轉載于:https://www.cnblogs.com/sfqtsh/p/5143678.html
總結
以上是生活随笔為你收集整理的RTTI: dynamic_cast typeid的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PICT实现组合测试用例
- 下一篇: 服务器系统小米随身wifi,win10系