鄭重聲明:本文是筆者根據個人理解所寫,錯誤難免,歡迎拍磚!
可以任意轉載、修改,轉載時是否標明出處,隨君而定!
static_cast
用於“良性”和“適度良性”轉換,包括不用強制轉換(如自動類型轉換)。static_cast全部用於明確定義的轉換,包括編譯器允許我們所做的不用強制轉換的“安全”轉換和不太安全但清楚定義的轉換。
用法:static_cast < type-id > ( expression)
該運算子把expression轉換為type-id類型,但沒有在運行時進行類型檢查來保證轉換的安全性。static_cast包含的類型轉換包括一下幾種:
A、典型的非強制變換
B、窄化(有資訊丟失)變換
C、使用void*的強制變換
D、隱式類型變換
E、類層次的靜態定位
a. 向上轉換是安全的,即將子類的指標或引用轉換為基類
b. 向下轉換是不安全的,即將基類指標或引用轉換成子類,因為是靜態轉換,沒有在運行時進行類型檢查,應使用dynamic_cast。
1 int i = 0x7fff; // max pos value = 32767 2 long l = 0; 3 float f = 1.0f; 4 5 // A: typeical castless conversions: 6 l = static_cast<long>(i); 7 8 // B: narrowing conversions: 9 i = static_cast<int>(f);10 11 // C: forcing a conversion from void* :12 void* pvoid = &i;13 float* pf = static_cast<float*>(pvoid);14 15 // D: Implicit type conversions, normally performed by the compiler16 double d = 0.0;17 int x = d; // Automatic type conversion18 x = static_cast<int>(d); // More explicit
注意:static_cast不能轉換掉expression的const、volitale、或者__unaligned屬性。
dynamic_cast
用法:dynamic_cast < type-id > ( expression )
該運算子把expression轉換成type-id類型的對象。type-id必須是類的指標、類的引用或者void *;
如果type-id是類指標類型,那麼expression也必須是一個指標,如果type-id是一個引用,那麼expression也必須是一個引用。
當使用dynamic_cast來試著向下類型轉換一個特定的類型,僅當類型轉換是爭取的並且是成功的時,傳回值是一個指向所需類型的指標,否則它將返回0來表示轉換失敗。
dynamic_cast主要用於類層次間的上行轉換和下行轉換,還可以用於類之間的交叉轉換。
在類層次間進行上行轉換時,dynamic_cast和static_cast的效果是一樣的;
在進行下行轉換時,dynamic_cast具有類型檢查的功能,比static_cast更安全。
1 #include <iostream> 2 using namespace std; 3 4 class CPet { public : virtual ~CPet() {} }; 5 class CDog : public CPet {}; 6 class CCat : public CPet {}; 7 8 int main() 9 {10 CPet* pPet = new CCat; // Upcast, safe11 // Try to cast it to CCat* :12 CCat* pCat = dynamic_cast<CCat*>(pPet); // cast success13 // Try to cast it to CDog* :14 CDog* pDog = dynamic_cast<CDog*>(pPet); // cast fail15 16 cout << "pDog = " << (long)pDog << endl;17 cout << "pCat = " << (long)pCat << endl;18 }
在上面的程式碼片段中,將pPet向下轉換為CCat*類型成功了(因為CPet* pPet = new CCat;),轉換為CDog*類型失敗了,說明dynamic_cast會進行類型檢測。
當使用dynamic_cast時,必須對一個真正多態的層次進行操作(即它含有虛函數),這是因為dynamic_cast使用了儲存在VTABLE中的資訊來判斷實際的類型。
注意:無論何時進行向下類型轉換,我們都應該進行類型檢查以確保轉換是成功的(即傳回值非0)。但我們不用確保指標要完全一樣,因為通常在向上和向下類型轉換時指標會進行調整(特別是多重繼承的情況下)。
dynamic _cast運行時需要一點額外的開銷,不多,但是執行大量的dynamic_cast時就說明我們的設計有問題了,也會導致效能損失。在進行向下轉換時,如果我們已經明確知道是什麼類型,就可以使用static_cast,以避免調用dynamic_cast產生的額外開銷。比如上面的將pPet向下轉換為CCat*類型,可以這樣寫:
CCat* pCat = static_cast<CCat*>(pPet);
reinterpret_cast
這是最不安全的一種轉換機制,最有可能出問題。reinterpret_cast把對象假象為模式(為了某種隱秘的目的),彷彿它是一個完全不同的類型對象。這是低級的位元模式,C因此而名稱不佳。在使用reinterpret_cast做任何事之前,實際上總是需要reinterpret_cast回到原來的類型(或者把變數看做是它原來的類型)。說白了,就是將原來的類型隱藏起來,用的時候再轉換回去,否則編譯失敗。
用法:reinterpret_cast< type-id > (expression)
type-id必須是一個指標、引用、算術類型、函數指標或者成員指標。
它可以把一個指標轉換成一個整數,也可以把一個整數轉換成一個指標(先把一個指標轉換成一個整數,
在把該整數轉換成原類型的指標,還可以得到原先的指標值)。
const_cast
const_cast用來修改類型的const或volatile屬性,即可以將const轉換為非const以及volatile轉換為非volatile,這是const_cast唯一允許的轉換。除了const 或volatile修飾之外, type_id和exdivssion的類型是一樣的。
用法:const_cast< type-id > (expression)
常量指標被轉化成非常量指標,並且仍然指向原來的對象;
常量引用被轉換成非常量引用,並且仍然指向原來的對象;常量對象被轉換成非常量對象。
Voiatile和const類試。舉如下一例:
1 class B 2 { 3 public: 4 int m_iNum; 5 } 6 void foo() 7 { 8 const B b1; 9 b1.m_iNum = 100; //comile error10 B b2 = const_cast<B>((b1);11 b2. m_iNum = 200; //fine12 }
上面的代碼編譯時間會報錯,因為b1是一個常量對象,不能對它進行改變;
使用const_cast把它轉換成一個常量對象,就可以對它的資料成員任意改變。注意:b1和b2是兩個不同的對象。
簡單總結一下:
dynamic_cast: 通常在基類和衍生類別之間轉換時使用;
const_cast: 主要針對const和volatile的轉換.
static_cast: 一般的轉換,如果你不知道該用哪個,就用這個。
reinterpret_cast: 用於進行沒有任何關聯之間的轉換,比如一個字元指標轉換為一個整形數。
參考資料:
http://blog.csdn.net/Lambol_8309/article/details/4534338
http://blog.sina.com.cn/s/blog_4a84e45b0100f57m.html