C 中4個與型別轉換相關的關鍵字( cast)

2021-08-22 00:12:05 字數 2802 閱讀 9749

在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...