轉載:http://www.weixueyuan.net/view/6377.html
在C++中,編譯期的類型轉換有可能會在運行時出現錯誤,特別是涉及到類對象的指針或引用操作時,更容易產生錯誤。Dynamic_cast操作符則可以在運行期對可能產生問題的類型轉換進行測試。
例1:
- #include<iostream>
- using namespace std;
- class base
- {
- public :
- void m(){cout<<"m"<<endl;}
- };
- class derived : public base
- {
- public:
- void f(){cout<<"f"<<endl;}
- };
- int main()
- {
- derived * p;
- p = new base;
- p = static_cast<derived *>(new base);
- p->m();
- p->f();
- return 0;
- }
產生這種運行期的錯誤原因在于static_cast強制類型轉換時并不具有保證類型安全的功能,而C++提供的dynamic_cast卻能解決這一問題,dynamic_cast可以在程序運行時檢測類型轉換是否類型安全。當然dynamic_cast使用起來也是有條件的,它要求所轉換的操作數必須包含多態類類型(即至少包含一個虛函數的類)。
例2:
- #include<iostream>
- using namespace std;
- class base
- {
- public :
- void m(){cout<<"m"<<endl;}
- };
- class derived : public base
- {
- public:
- void f(){cout<<"f"<<endl;}
- };
- int main()
- {
- derived * p;
- p = new base;
- p = dynamic_cast<derived *>(new base);
- p->m();
- p->f();
- return 0;
- }
dynamic_cast還要求<>內部所描述的目標類型必須為指針或引用。如例3所示,如果我們將例2中的主函數換成例3的形式,這也是無法通過編譯的。
例3:
- int main()
- {
- base b;
- dynamic_cast<derived>(b);
- return 0;
- }
例4:
#include<iostream> using namespace std;class base { public :virtual void m(){cout<<"m"<<endl;} };class derived : public base { public:void f(){cout<<"f"<<endl;} };int main() {derived * p;p = dynamic_cast<derived *>(new base);if(p){p->m();p->f(); }elsecout<<"Convert not safe!"<<endl;return 0; }在本例中通過dynamic_cast來初始化指針p,在初始化過程中dynamic_cast會檢測操作數new base轉換為目標類型derived *是否能保證類型安全,如果類型安全則將new base結果賦給p指針,否則返回0,也即false。而本例中是要用基類對象地址去初始化派生類指針,這顯然是無法保證類型安全的,因此p最后得到的返回值是0。在主函數中經過判斷語句,最終程序輸出“Convert not safe!”。
Dynamic_cast轉換有自己的規則,下面將通過示例來介紹轉換規則。
例4:
- #include<iostream>
- using namespace std;
- class base
- {
- public :
- virtual void m(){cout<<"m"<<endl;}
- };
- class derived : public base
- {
- public:
- virtual void f(){cout<<"f"<<endl;}
- };
- int main()
- {
- derived * d;
- d = dynamic_cast<derived *>(new base);
- if(d)
- {
- cout<<"Base to Derived is ok"<<endl;
- delete d;
- }
- else
- cout<<"Base to Derived is error"<<endl;
- base * b;
- b = dynamic_cast<base *>(new derived);
- if(b)
- {
- cout<<"Derived to Base is ok"<<endl;
- delete b;
- }
- else
- cout<<"Derived to Base is error"<<endl;
- return 0;
- }
??? Base to Derived is error
??? Derived to Base is ok
從結果可以看出從不能將指向基類對象的指針轉換為指向派生類對象的指針,但是可以將指向派生類對象的指針轉換為指向基類對象的指針。
例5:
- #include<iostream>
- using namespace std;
- class A
- {
- public :
- virtual void m(){cout<<"m"<<endl;}
- };
- class B
- {
- public:
- virtual void f(){cout<<"f"<<endl;}
- };
- int main()
- {
- A * a;
- a = dynamic_cast<A *>(new B);
- if(a)
- {
- cout<<"B to A is ok"<<endl;
- delete a;
- }
- else
- cout<<"B to A is error"<<endl;
- B * b;
- b = dynamic_cast<B *>(new A);
- if(b)
- {
- cout<<"A to B is ok"<<endl;
- delete b;
- }
- else
- cout<<"A to B is error"<<endl;
- return 0;
- }
??? B to A is error
??? A to B is error
從程序運行結果不難看出,任意兩個不相關的多態類類型之間的轉換也是不能進行的。
總結一下dynamic_cast轉換規則,只允許指向派生類對象的指針轉換為指向基類對象的指針。
C++提供的兩個類型轉換操作符static_cast和dynamic_cast,static_cast可以用于任何類型的強制類型轉換,但是它不保證轉換過程中的類型安全,dynamic_cast只能用于多態類類型的轉換,而且要求轉換的目的類型必須為指針或引用,并且它可以保證轉換過程中類型安全。