C 中的顯式型別轉化

2021-09-20 05:44:22 字數 3079 閱讀 6238

型別轉化也許大家並不陌生,int i; float j; j = (float)i; i = (int)j; 像這樣的顯式轉化其實很常見,強制型別轉換可能會丟失部分資料,所以如果不加(int)做強制轉換,嚴檢查的編譯會報錯,寬檢查的編譯會報warning。在c語言中,指標是4位元組或者8位元組的,所以指標之間的強制轉換在轉換的時候就如同不同的整數型別之間的賦值,問題在於對該指標的使用上,必須確保該指標確實可以做出這樣的強制轉換。常見的情況是void*到不同的指標型別(比如記憶體分配,引數傳遞),char*和unsigned char*這樣的轉換。也有在讀檔案的時候,直接把某個結構對映為記憶體,寫檔案的時候,把某塊記憶體直接對映成結構體。但其實在c++中,有用於專門用於顯示型別轉化的更合適更安全的語法。

主要包括四種:static_cast、const_cast、reinterpret_cast、dynamic_cast。四種轉化的用途各不相同,下面一一介紹:

一、static_cast(靜態轉化)

語法:a = static_cast(b)

把b顯式轉化為typea型別,static_cast是最常用到的轉化操作符,使用它可以消除因產生型別轉化而可能產生的編譯器warnings,static_cast全部用於明確定義的變換,包括編譯器允許我們做的不用強制轉換的「安全」變換和不太安全但清楚定義的變換。static_cast包含的轉化型別包括典型的非強制型別轉換、窄化變化(會有資訊丟失)、使用void*的強制變換、隱式型別變換和類層次的靜態定位(基類和派生類之間的轉換)。

說明**如下:

1 #include 2

using

namespace

std;34

void func(int

){}5

6int

main()

更重要的應用是在於基類與派生類之間的轉換

class base{};   

class derv:public base{};

derv dd;

base bb = static_cast(dd);//具有繼承關係的型別之間轉換

base *pb = new base;

derv *pd = static_cast(pb);//基類轉繼承類

derv* pd1 = new derv;

base* pb1 = static_cast(pd1);//繼承類指標轉父類指標

二、const_cast(常量轉換

語法:a = const_cast(b)

這個運算子可以用來去除乙個物件的const或volatile屬性。typea必須是乙個指標或者引用。

1 #include 2

using

namespace

std;

3int

main()

三、reinterpret_cast(重解釋轉換)

語法:a = reinterpret_cast(b)

這是一種最不安全的轉換,最有可能出現問題,reinterpret_cast把物件假想為模式,彷彿它是乙個完全不同型別的物件,這是低階的位操作,修改了運算元型別,但僅僅重新解釋了物件的位元模型而沒有進行二進位制轉換,在使用reinterpret_cast做任何事情之前,實際上總是需要它回到原來的型別。

從語法上看,這個操作符僅用於指標型別的轉換(返回值是指標)。它用來將乙個型別指標轉換為另乙個型別指標,它只需在編譯時重新解釋指標的型別。

這個操作符基本不考慮轉換型別之間是否是相關的。

reinterpret_cast的本質(一文做的試驗很好的解釋了reinterpret_cast不做二進位制轉換的特點。我喜歡從c語言的角度來理解這個操作符,就像c語言中的指標強制轉換,其實只是把位址賦給了新的指標,其它的不做改變,只在新的指標使用的時候,進行不一樣的解釋。看如下的例子:

1 #include 2

using

namespace

std;

3const

int sz = 100;4

5struct

x ;8

9void print(x*x)

1415

intmain()

reinterpret_cast的思想就是當需要使用的時候,得到的東西已經轉換成不同的型別了,以至於它不能用於型別原來的目的,除非再次把它轉換回來。這裡列印呼叫中轉換回x*。xp只有作為int*才有用,這是對原來的x的重新解釋。使用renterpret_cast通常不是乙個明智的做法,但是當需要用到的時候,它是十分有用的。

reinterpret_cast常用的場景如下:

1)普通指標轉換,t*—>u*—>t*,保證t*經過一些列轉換值不變

比如將不同型別的指標存在乙個容器裡,vector可以存int*,char*,string*等各種指標,只要有別的方式確定某個void*當初的型別是t*,標準保證reinterpret_cast(v[i])可以得到當初的值。

2)自己做memory allocator,可以將t*轉換為u*,這個時候可能要注意位元組對其的問題。

四、dynamic_cast(動態轉換)

語法:a=dynamic_cast(b)

該運算子把b轉換成typea型別的物件。typea必須是類的指標、類的引用或者void *;

dynamic_cast的轉換是在執行時進行的,它的乙個好處是會在執行是做型別檢查,如果物件的型別不是期望的型別,它會在指標轉換的時候返回null,並在引用轉換的時候丟擲乙個std::bad_cast異常。

dynamic_cast一般只在繼承類物件的指標之間或引用之間進行型別轉換。如果沒有繼承關係,則被轉化的類具有虛函式物件的指標進行轉換。

1

structa 3

};4struct b : public

a ;5

struct

c ;6

7void

f ()

真正重要的東西,用眼睛是看不見的。 

C 中的顯式型別轉化

型別轉化也許大家並不陌生,int i float j j float i i int j 像這樣的顯式轉化其實很常見,強制型別轉換可能會丟失部分資料,所以如果不加 int 做強制轉換,嚴檢查的編譯會報錯,寬檢查的編譯會報warning。在c語言中,指標是4位元組或者8位元組的,所以指標之間的強制轉換...

C 中的顯式型別轉化

型別轉化也許大家並不陌生,int i float j j float i i int j 像這樣的顯式轉化其實很常見,強制型別轉換可能會丟失部分資料,所以如果不加 int 做強制轉換,嚴檢查的編譯會報錯,寬檢查的編譯會報warning。在c語言中,指標是4位元組或者8位元組的,所以指標之間的強制轉換...

C 中的顯式型別轉換

寫c 的時候,有時候不可避免的會使用型別轉換,良好的編碼風格中應該避免隱式轉換,隱式轉換有時候會產生不易察覺的問題。c 提供了四種顯示型別轉換方式,當然顯示的強制型別轉換也是需要盡量避免的。四種顯示轉換具有相同的形式 cast name expression type 是轉換的目標型別 expres...