C++中有四種類型轉換關鍵字,分別是reinterpret_cast,static_cast,const_cast,dynamic_cast.這是C++
為了減少強制轉換的副作用,并且在查錯時使程序員能夠快速定位(總是最值得懷疑的)強制轉換,在標準C++中新增加了4個關鍵字*_cast,用來提倡一種全新的C++顯式轉換語法:
?_cast<type?id>(expression)
- reinterpret_cast
主要用在底層代碼中,實現任意指針之間的轉換和指針與整數之間的轉換,這是一種最有可能出問題的最不安全的類型轉換。只是在下面的情形,才需要使用這種類型轉換:當需要使用時,所得到的東西已經不同了,為了使它能夠用于原來的目的,必須再次把它轉換回來。例如:
const int sz = 100; // 定義數組大小,標準C++提倡用常型變量(而不是常數或
// 符號常量宏)
struct X {int a[sz];}; // 只包含一個整數數組的結構
X x; // 定義結構變量,此時結構中的數組元素的值無意義(需要初始化)
int *px = reinterpret_cast<int *> (&x); // 為了初始化,先把結構轉化為int數組
for (int *i = px; i < px + sz; i++) *i = 0; // 將每個數組元素的值初始化為0
print(reinterpret_cast<X *> (px)); // 重新轉換成結構指針,以便使用
// 也可以直接使用原來的標識符x
// 此語句相當于print(&x);
使用reinterpret_cast通常是一種不明智且不方便的編程方式。但是在必須使用時,它也是非常有用的。
2. static_cast
用于強制類型隱式轉換,可以用于指針之間、引用之間或者基礎類型之間的轉換。應用到類的指針上,意思是說它允許子類類型的指針轉換為父類類型的指針(這是一個有效的隱式轉換)。
注意:被轉換的父類沒有被檢查是否與目的類型相一致。
代碼:
class Base {};
class Derived : public Base {};
Derived *a = new Derived ;
Base *b = static_cast<Base *>(a);
'static_cast'除了操作類型指針,也能用于執行類型定義的顯式的轉換,以及基礎類型之間的標準轉換:
代碼:
double d = 3.14159265;
int i = static_cast<int>(d);
3、dynamic_cast
主要只用于對象的指針和引用。當用于多態類型時,它允許任意的隱式類型轉換以及相反過程。不過,與static_cast不同,在后一種情況里(注:即隱式轉換的相反過程),dynamic_cast會檢查操作是否有效。也就是說,它會檢查轉換是否會返回一個被請求的有效的完整對象。檢測在運行時進行。如果被轉換的指針不是一個被請求的有效完整的對象指針,返回值為NULL.
通常用來執行一種安全的向下類型轉換(downcast)操作,用于在一個類繼承層次上向下移動。
因為每個派生類的基類都只有一個,而且派生類本身又包含了幾乎所有的基類信息(private型的除外),所以向上的類型轉換(upcast)總是唯一的和比較安全的(可以使用static_cast轉換)。
而一個基類往往有多個派生類,而且派生類中一般會在基類的基礎上添加了一些特有的數據和操作,所以向下的類型轉換總是多態的和不太安全的。
dynamic_cast提供了一種安全的向下類型轉換操作,只有當類型轉換是正確的并且轉換取的成功,返回值才是所需要的指針;否則它將返回0(空指針NULL),表示不是正確的類型。
class Pet {……};
class Dog : public Pet {……};
class Cat : public Pet {……};
……
Pet *pPet = new Cat; // 向上的類型轉換
Dog *pDog = dynamic_cast<Dog *>(pPet); // 類型錯誤,返回0(NULL)
Cat *pCat = dynamic_cast<Cat *>(pPet); // 類型正確,返回指針
Cat *pCat = static_cast<Cat *>(pPet); // 正確,減少運行時的開銷
4.const_cast
用來去除指針或者引用的常量性,即
const_cast (expression)
該運算符用來修改類型的const或volatile屬性。除了const 或volatile修飾之外, type_id和expression的類型是一樣的。
一、常量指針被轉化成非常量的指針,并且仍然指向原來的對象;
二、常量引用被轉換成非常量的引用,并且仍然指向原來的對象;
const int i = 0;
int *pi;
pi = &i; // 錯誤
pi = (int *)&i; // 被反對
pi = const_cast<int *>(&i); // 完美
long *pl = const_cast<long *>(&i); // 錯誤
volatile int k = 0;
int *pk = const_cast<int *>(&k); // 正確
在這四種強制轉換中,static_cast最常用(目前還沒有流行起來,但是被標準C++著力提倡)、dynamic_cast最重要、const_cast也有用、而reinterpret_cast則很少被使用。