C++風格的四種類型轉換方法:static_cast、dynamic_cast、reinterpret_cast、const_cast。
歡迎來到 lovickie 的博客 http://www.cnblogs.com/lovickie
使用 static_cast 可以進行接近C風格的靜態轉換,但增加了安全性考慮。
double d = 3.14; int i = static_cast<int> (d);
歡迎來到 lovickie 的博客 http://www.cnblogs.com/lovickie
上行轉換(子類指針轉父類指針)一般是安全的,當然必須得 public 繼承才合法。下行轉換(父類指針轉子類指針)很可能不安全(例如當指針指向父類對象時)。
可以采用 dynamic_cast<type> (expression) 動態轉換的條件是:type為指針或引用,下行轉換時基類為多態(有虛函數,從而可以在虛表中放一個類型信息指針—— dynamic_cast 的一種典型實現)。對於不安全的指針下行轉換,dynamic_cast 返回 NULL。
class Dad {}; class Son: public Dad { public: void func (); }; int main () { Dad d; Son *s1 = (Son*) &d; // 編譯通過 s1->func (); // 運行出錯 Son *s2 = static_cast<Son*> (&d); // 編譯報錯: 無法轉換 s2->func (); Son *s3 = dynamic_cast<Son*> (&d); // 編譯報錯: Dad不是多態類型, 除非Dad中有虛函數 }
class Dad { virtual void func (); }; class Son: public Dad {}; int main () { Son son; Dad *pd = dynamic_cast<Dad*> (&son); // 上行轉換, ok Dad dad; Son *ps = dynamic_cast<Son*> (&dad); // 下行轉換, ps=0 Dad *pdad = new Dad, *pson = new Son; ps = dynamic_cast<Son*> (pdad); // 下行轉換, ps=0 ps = dynamic_cast<Son*> (pson); // 下行轉換, ok }
如上面這個例子所示,對指針下行轉換時,如果失敗 dynamic_cast 會返回0;而對引用下行轉換時,如果失敗會拋出 bad_cast 異常。
void f (Dad &dad) { try { Son &son = dynamic_cast<Son&> (dad); } catch ( bad_cast ) { // 異常處理 } }
當轉換源指針或目標指針為 void * 時,dynamic_cast 總認為安全。目標指針為 void * 可以用於確定多態類型的對象的起始地址。
class A { virtual void func (); }; int main () { A *a = new A; void *v = dynamic_cast<void*> (a); // 同樣要求A多態 a = dynamic_cast<A*> (v); }
和 typeid 一樣,dynamic_cast 使用了“運行時類型信息” RTTI(Run Time Type Information),某些平台可能不支持。
歡迎來到 lovickie 的博客 http://www.cnblogs.com/lovickie
使用 reinterpret_cast<type> (expression) 可以在指針之間或指針與整數之間轉換類型,同樣要求 type 為指針或引用。
int *p = new int; long i = reinterpret_cast<long> (p); p = 0; // p 不再指向 new int p = reinterpret_cast<int*> i; // p 重新指向 new int
歡迎來到 lovickie 的博客 http://www.cnblogs.com/lovickie
使用 const_cast 可以將常量轉換為變量,去除 const 屬性。
const char *str = "hello"; char *s = const_cast<char*> (str);
在類 A 的 const 成員函數中,如果想要修改 A 的成員變量,可以先將 this 強制去除 const 屬性。但當對象本身就是常量時,結果將不可預見。
class A { bool m; public: void func () const { A *a = const_cast<A*> (this); // 強制去除const屬性 a->m = true; } }; int main () { A a1; const A a2; a1.func (); // ok a2.func (); // 無定義行為 }
因此,令某些成員變量可被 const 成員函數修改的更好的解決方案是,將成員變量聲明為 mutable,或者將這些成員變量封裝到結構體指針中。
歡迎來到 lovickie 的博客 http://www.cnblogs.com/lovickie
無。