1. 程式人生 > >c++ 四種類型轉化方式

c++ 四種類型轉化方式

宣告:轉載出處:轉自此處

C風格的強制型別轉換(Type Cast)很簡單,不管什麼型別的轉換統統是:TYPE b = (TYPE)a,但是c 風格的型別轉換有不少的缺點,有的時候用c風格的轉換是不合適的,因為它可以在任意型別之間轉換,比如你可以把一個指向const物件的指標轉換成指向非 const物件的指標,把一個指向基類物件的指標轉換成指向一個派生類物件的指標,這兩種轉換之間的差別是巨大的,但是傳統的c語言風格的型別轉換沒有區 分這些。還有一個缺點就是,c風格的轉換不容易查詢,他由一個括號加上一個識別符號組成,而這樣的東西在c++程式裡一大堆。所以c++為了克服這些缺點,引進了4種類型轉換操作符(C++風格的強制轉換其他的好處是,它們能更清晰的表明它們要幹什麼。程式設計師只要掃一眼這樣的程式碼,就能立即知道一個強制轉換的目的。):

1、static_cast:可以實現C++中內建基本資料型別之間的相互轉換,enum、struct、 int、char、float等。它不能進行無關型別(如非基類和子類)指標之間的轉換。

int c=static_cast(7.987);

如果涉及到類的話,static_cast只能在有相互聯絡的型別中進行相互轉換,不一定包含虛擬函式。

class A
{};
class B:public A
{};
class C
{};

int main()
{
    A* a=new A;
    B* b;
    C* c;
    b=static_cast<B>(a);  // 編譯不會報錯, B類繼承A類
c=static_cast<B>(a); // 編譯報錯, C類與A類沒有任何關係 return 1; }

2、const_cast: const_cast操作不能在不同的種類間轉換。相反,它僅僅把一個它作用的表示式轉換成常量。它可以使一個本來不是const型別的資料轉換成const型別的,或者把const屬性去掉。

3、reinterpret_cast: (interpret是解釋的意思,reinterpret即為重新解釋,此識別符號的意思即為資料的二進位制形式重新解釋,但是不改變其值。)有著和C風格的強制轉換同樣的能力。它可以轉化任何內建的資料型別為其他任何的資料型別,也可以轉化任何指標型別為其他的型別。它甚至可以轉化內建的資料型別為指標,無須考慮型別安全或者常量的情形。不到萬不得已絕對不用。

4、dynamic_cast:
(1)其他三種都是編譯時完成的,dynamic_cast是執行時處理的,執行時要進行型別檢查。
(2)不能用於內建的基本資料型別的強制轉換。
(3)dynamic_cast轉換如果成功的話返回的是指向類的指標或引用,轉換失敗的話則會返回NULL。
(4)使用dynamic_cast進行轉換的,基類中一定要有虛擬函式,否則編譯不通過。
需要檢測有虛擬函式的原因:類中存在虛擬函式,就說明它有想要讓基類指標或引用指向派生類物件的情況,此時轉換才有意義。
這是由於執行時型別檢查需要執行時型別資訊,而這個資訊儲存在類的虛擬函式表(關於虛擬函式表的概念)中,
只有定義了虛擬函式的類才有虛擬函式表。
(5) 在類的轉換時,在類層次間進行上行轉換時,dynamic_cast和static_cast的效果是一樣的。在進行下行轉換 時,dynamic_cast具有型別檢查的功能,比 static_cast更安全。向上轉換即為指向子類物件的向下轉換,即將父類指標轉化子類指標。向下轉換的成功與否還與將要轉換的型別有關,即要轉換的指標指向的物件的實際型別與轉換以後的物件型別一定要相同,否則轉換失敗。

例如:

#include<iostream>
#include<cstring>
using namespace std;
class A
{
   public:
   virtual void f()
   {
       cout<<"hello"<<endl;
       };
};

class B:public A
{
    public:
    void f()
    {
        cout<<"hello2"<<endl;
        };

};

class C
{
  void pp()
  {
      return;
  }
};

int fun()
{
    return 1;
}
int main()
{
    A* a1=new B;//a1是A型別的指標指向一個B型別的物件
    A* a2=new A;//a2是A型別的指標指向一個A型別的物件
    B* b;
    C* c;
    b=dynamic_cast<B*>(a1);//結果為not null,向下轉換成功,a1之前指向的就是B型別的物件,所以可以轉換成B型別的指標。
    if(b==NULL)
    {
        cout<<"null"<<endl;
    }
    else
    {
        cout<<"not null"<<endl;
    }
    b=dynamic_cast<B*>(a2);//結果為null,向下轉換失敗
    if(b==NULL)
    {
        cout<<"null"<<endl;
    }
    else
    {
        cout<<"not null"<<endl;
    }
    c=dynamic_cast<C*>(a);//結果為null,向下轉換失敗
    if(c==NULL)
    {
        cout<<"null"<<endl;
    }
    else
    {
        cout<<"not null"<<endl;
    }
    delete(a);
    return 0;
}