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
無。