在c/c++語言中用 (type) value(在c++還可以採用type(value))來進行顯式型別轉換(explicit type conversion),常常又被稱為強制轉換(cast投射/鑄模)。這種轉換的正確性完全掌握在程式設計師手中,傳統上強制轉換往往被過度使用,成為c++程式犯錯的乙個主要根源。
為了減少強制轉換的***,並且在查錯時使程式設計師能夠快速定位(總是最值得懷疑的)強制轉換,在標準c++中新增加了4個關鍵字*_cast,用來提倡一種全新的c++顯式轉換語法:
*_cast (expression)
l static_cast(靜態轉換):用於明確定義良性和適度良性的轉換,包括原來不需要採用強制轉換的自動型別轉換(包括無損的提公升轉換和可能丟失資訊的窄化轉換[narrowing conversion],對後者編譯器一般會提出警告)。標準c++提倡對任何資料的型別轉換(不論是自動的還是強制的),都採用新的*_cast顯式型別轉換方法。例如:
int i = 0x7fff;
long l;
float f;
char c;
// (1)典型的非強制轉換(自動轉換)
// 傳統方式:
l = i;
f = i;
// 提倡的新方式:
l = static_cast(i);
f = static_cast(i);
// (2)窄化轉換
// 傳統方式:
// 會顯示警告資訊:
i = l; // 可能丟失數字
i = f; // 可能丟失資訊
c = i; // 可能丟失數字
// 不顯示警告資訊(但仍然難定位):
i = (int)l;
i = (int)f;
c = (char)i;
// 提倡的新方式(不會顯示警告資訊,且易定位):
i = static_cast(l);
i = static_cast(f);
c = static_cast(i);
l const_cast(常量轉換):可將(同資料型別的)常型(const)轉換為非常型、將易變(volatile)型轉換為非易變型。如果用於其他型別的轉換,一般會產生乙個編譯錯誤。例如:
const int i = 0;
int *pi;
pi = &i; // 錯誤
pi = (int *)&i; // 被反對
pi = const_cast(&i); // 完美
long *pl = const_cast(&i); // 錯誤
volatile int k = 0;
int *pk = const_cast(&k); // 正確
l dynamic_cast(動態轉換):一種安全的向下型別轉換(downcast)操作,用於在乙個類繼承層次上向下移動。
因為每個派生類的基類都只有乙個,而且派生類本身又包含了幾乎所有的基類資訊(private型的除外),所以向上的型別轉換(upcast)總是唯一的和比較安全的。
而乙個基類往往有多個派生類,而且派生類中一般會在基類的基礎上新增了一些特有的資料和操作,所以向下的型別轉換總是多型的和不太安全的。
dynamic_cast提供了一種安全的向下型別轉換操作,只有當型別轉換是正確的並且轉換取的成功,返回值才是所需要的指標;否則它將返回0(空指標null),表示不是正確的型別。
例如:class pet ;
class dog : public pet ;
class cat : public pet ;
pet *ppet = new cat; // 向上的型別轉換
dog *pdog = dynamic_cast(ppet); // 型別錯誤,返回0(null)
cat *pcat = dynamic_cast(ppet); // 型別正確,返回指標
cat *pcat = static_cast(ppet); // 正確,減少執行時的開銷
注意:dynamic_cast雖然安全,但是執行時需要一定開銷,因此不提倡大量使用這種轉換。如果你已經能夠確認轉換的正確性,則可以採用前面介紹過的(無執行時開銷的)static_cast轉換。只有當你實在無法確定轉換是否正確時,才需要採用dynamic_cast轉換。
l reinterpret_cast(重解釋轉換):一種最有可能出問題的最不安全的型別轉換。只是在下面的情形,才需要使用這種型別轉換:當需要使用時,所得到的東西已經不同了,為了使它能夠用於原來的目的,必須再次把它轉換回來。例如:
const int sz = 100; // 定義陣列大小,標準c++提倡用常型變數(而不是常數或
// 符號常量巨集)
struct x ; // 只包含乙個整數陣列的結構
x x; // 定義結構變數,此時結構中的陣列元素的值無意義(需要初始化)
int *px = reinterpret_cast(&x); // 為了初始化,先把結構轉化為int陣列
for (int *i = px; i < px + sz; i++) *i = 0; // 將每個陣列元素的值初始化為0
print(reinterpret_cast(px)); // 重新轉換成結構指標,以便使用
// 也可以直接使用原來的識別符號x
// 此語句相當於print(&x);
使用reinterpret_cast通常是一種不明智且不方便的程式設計方式。但是在必須使用時,它也是非常有用的。
在這四種強制轉換中,static_cast最常用(目前還沒有流行起來,但是被標準c++著力提倡)、dynamic_cast最重要、const_cast也有用、而reinterpret_cast則很少被使用。
C 中4個與型別轉換相關的關鍵字
static cast const cast dynamic cast reinterpret cast 表示式是否合法取決於運算元的型別,而且合法的表示式其含義也由運算元型別決定。在c 中,某些型別之間存在相關的依賴關係。若兩種型別相關,則可在需要某種型別的運算元位置上,使用該型別的相關型別物件或...
C 與型別轉換相關的4個關鍵字
首先,c 與型別轉換相關的四個關鍵字有 const cast,static cast,dynamic cast,reinterpret cast.什麼是型別轉換?表示式是否合法取決於運算元的型別,而且合法的表示式其含義也由運算元型別決定。但是在c 中,某些型別之間存在相關的依賴關係。若兩種型別相關,...
c 中4個與型別轉換相關的關鍵字分析
static cast reinterpret cast dynamic cast const cast 1.static cast 運算子完成相關型別之間的轉換 使用場景 如在同一類層次結構中的乙個指標型別到另乙個指標型別,整型到列舉型別,或者浮點型到整型等。例 1,int m 10 double...