程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 【C++】類型轉換,類型轉換

【C++】類型轉換,類型轉換

編輯:C++入門知識

【C++】類型轉換,類型轉換


  • 引言

  C++風格的四種類型轉換方法:static_cast、dynamic_cast、reinterpret_cast、const_cast。

  歡迎來到 lovickie 的博客 http://www.cnblogs.com/lovickie

  • static_cast

  使用 static_cast 可以進行接近C風格的靜態轉換,但增加了安全性考慮。

double d = 3.14;
int i = static_cast<int> (d);

  歡迎來到 lovickie 的博客 http://www.cnblogs.com/lovickie

  • dynamic_cast

  上行轉換(子類指針轉父類指針)一般是安全的,當然必須得 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

  使用 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_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

  • 結語

  無。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved