C 型別轉換運算子

2021-10-07 20:42:19 字數 3155 閱讀 7331

目錄

dynamic_cast

static_cast

const_cast

reinterpret_cast

c語言的型別轉換比較自由,但也帶來了一些問題,這些問題大多由程式設計師自行控制和解決。對於龐大的c++語言機制而言,這種簡單粗暴的型別轉換方式顯然是個巨大的負擔,因此c++引入4種型別轉換運算子,更加嚴格的限制允許的型別轉換,使轉換過程更加規範:

其中,const_cast和reinterpret_cast的使用會帶來更大的風險,因此不到萬不得已,不推薦使用。

//將p轉化為type型別

dynamic_cast(p);

注意:

轉換型別必須是乙個指標、引用或者void*,用於將基類的指標或引用安全地轉換成派生類的指標或引用;

dynamic_cast在執行期間強制轉換,執行時進行型別轉換檢查;

對指標進行轉換,失敗返回null,成功返回type型別的物件指標,對於引用的轉換,失敗丟擲乙個bad_cast ,成功返回type型別的引用;

dynamic_cast不能用於內建型別的轉換;

用於類的轉換,基類中一定要有virtual定義的虛函式(保證多型性),不然會編譯錯誤。

dynamic_cast最常用的場景就是將原本「指向派生物件的基類指標或引用」公升級為「派生類指標或引用」。

#includeusing namespace std;

// 基類

class base ;

virtual ~base() {};

};//派生類

class derived :public base ;

};int main()

else

base = new base;

if (derived* derived = dynamic_cast(base))

else

cin.get();

return 0;

}

第一種情況,先讓基類的指標指向派生類物件,這是一種「向上轉換」(upcasting),可以直接隱式轉換,合乎語法。然後令基類指標「公升級為」派生類指標,原則上,這是一種「向下轉換」(downcasting),需要顯示強制轉換,但指向的記憶體是派生類的,派生類指標指向派生類的記憶體,理論上不存在安全隱患,所以用dynamic_cast進行強轉,沒任何問題。

第二種情況,令派生類指標指向基類物件,顯然是存在安全隱患,dynamic_cast會返回乙個null指標,告訴開發者轉換失敗了。但這個操作發生在執行時。

dynamic_cast和傳統的(type)(expression)強制轉換的最大區別在於提供了執行時的型別檢查,保證了型別安全,使用強制轉換,會跳過編譯器的型別檢查,但可能會造成執行時異常,導致程式直接崩潰。

static_cast(p);
作用: 與dynamic_cast作用類似,將p轉換為type型別,區別在於,static發生於編譯時,dynamic發生於執行時。

#includeusing namespace std;

class another {};

class base {};

class derived :public base {};

int main()

const_cast(expression);

1作用: 彌補了static_cast無法轉換const/volitale的不足,將expression的const/volitale屬性移除,僅限於底層const屬性.

備註:① 頂層const:表示指標變數是const的,比如int *const pointer;,底層const:表示指標所指向的變數是const的,比如const int *pointer;。理解記憶:所謂底層const就是指我這個變數「底子」就是const,改不了,天生麗質難自棄。反之,則是頂層const。

② const_cast不能執行其他任何型別轉換,只能用於同型別之間不同const/volitale屬性的移除。否則會報編譯時錯誤。

③ 需要注意的是,const_cast通常對指標和引用進行轉換,而無法直接移除內建型別的const/volitale屬性,換言之,這種語法直接提供了乙個具有寫許可權的指標或引用,可以通過間接訪問的方式,修改常量。

#includeusing namespace std;

int main()

通過const_cast 常量a被修改。但是這裡有個有趣的現象,就是,指向a的 指標b被修改了,但是a本身卻還是沒變,從位址上看,指標b確實指向了常量a,但是*b和a卻不一樣,這是為什麼呢?

推測可能是編譯器(這裡用的visual studio 2017)對字面型常量的引用,有自己的優化,所以a的值沒有發生更改,但實際上已經改了,比如換種方式——

#includeusing namespace std;

int main()

這時會發現,常量a也能改變了(但仍然無法使用a = 30這樣的賦值語句來改變a)。

reinterpret_cast(expression);

作用: reinterpret_cast 允許將任何指標轉換為任何其他指標型別。 也允許將任何整數型別轉換為任何指標型別以及反向轉換。

備註:① reinterpret_cast 運算子可用於 char* 到 int* 或 one_class* 到 unrelated_class* 之類的轉換,這本身並不安全,但可以通過編譯;

② reinterpret_cast 的本質作用是重新定義記憶體資料的解釋方式,而不進行任何二進位制轉換。

舉個例子:

char s = "hello world!";

long l= reinterpret_cast(s);// 這裡的作用是取字串s的位址,位址轉換成了long型;

cout << "l = " << l << endl;

總結

c++提供了這四種型別強制轉換符,主要作用是應對更高階的語法,以及更複雜的情況,以保證更好的安全性。畢竟c++的高階語法,還是蠻複雜的,如果型別轉換像c語言一樣自由而沒有限制,必然會帶來一連串問題。這種機制,一定程度上限定了型別轉換的「規則」。

但對於比較簡單的型別轉換,大可不必這麼複雜,直接用強制轉換(而不是強制轉換運算子)即可。

c 型別轉換運算子

c 中有4個型別轉換運算子,使裝換過程更規範 dynamic cast type name expression 如果轉型失敗則返回0,即空指標。該運算子的用途是,使得能夠在類層次結構中進行向上轉換 由於 is a關係,這樣的型別轉換時安全的 而不允許其他轉換。二 const cast const ...

C 型別轉換運算子

隱式轉換,是針對不同型別之間的賦值和運算,函式呼叫傳遞引數 這些的轉換都是由編譯器自動完成 char ch int i ch 顯式轉換 由程式設計師在變數前面新增型轉換 char pc char pb void ps void pa 通過上述的兩種方式,c語言大部分的型別轉換都可以順利進行,c 繼承...

C 型別轉換運算子

用於 指向派生類物件的 基類指標轉換成派生類指標。如果轉換失敗,則返回0,即空指標。通過判斷轉換是否成功,來決定是否用派生類裡的函式 基類中可能沒有那個函式 class a class b public a class c public b a a new a a b new b a c new c...