1、 型別轉換
1、在下面這些表示式中,編譯器會自動轉換運算物件的型別:
(1) 在大多數表示式中,比int型別小的整型值首先提公升為較大的整數型別。
(2) 在條件中,非布林值轉換成布林型別。
(3) 初始化過程中,初始值轉換成變數的型別;在賦值語句中,右側運算物件轉換成左側運算物件的型別。
(4) 如果算術運算或關係運算的運算物件有多種型別,需要轉換成同一種型別。
1.1、算術轉換
1.1.1、運算子的運算物件將轉換成最寬的型別。
1.1.2、當表示式中既有浮點型別也有整形型別時,整數值將轉換成相應的浮點型別。
1.1.3、整型提公升負責把小整數型別轉換成較大的整數型別。對於bool、char、signed char、unsigned char、short和unsigned short等型別來說,只要它們所可能都能存在於int裡,它們就會提公升成int型別。否則提公升成unsigned int型別。較大的char型別(wchar_t、char16_t、char32_t)提公升成int、unsigned int、long、unsigned long、long long 和unsigned long long中最小的一種型別。前提是轉換後的型別要能容納原型別所有可能的值。
1.1.4、對於無符號型別和有符號型別運算
(1) 如果無符號型別不小於帶符號型別,那麼帶符號的運算物件轉化成無符號的
(2) 如果帶符號型別大於無符號型別,那麼若無符號型別的所有值都能存在該帶符號型別中,則無符號型別的運算物件轉換成帶符號類 型。若不能,則帶符號型別的運算物件轉換成無符號型別。
1.1.5、例子
3.14159l + 'a'; //'a'提公升成int,然後該int值轉換成long double
double dval;
int ival = dval; //dval轉換成(切除小數部分後)int
bool flag = dval; //如果dval為0,則flag為false;如果dval為1,則flag為1
char cval;
float fval;
cval + fval; //cval提公升成int,然後該int值轉換成float
short sval;
cval + sval; //cval和sval都提公升成int,sizeof(cval+sval)結果是4
long lval;
cval + lval; //cval直接轉成long,不用先轉成int,因為都是整型,而且long比int大
unsigned long ulval;
ival + ulval; //ival轉成unsigned long
unsigned short usval;
usval + ival; //根據unsigned short 和 int所佔空間的大小進行提公升
unsigned int uival;
uival + lval; //根據unsigned int 和 long所佔空間的大小進行提公升
1.2、 其他隱式型別轉換
1.2.1、陣列轉化成指標:在大多數用到陣列的表示式中,陣列自動轉換成指向陣列首元素的指標。
(1) 當陣列被用作decltype關鍵字的引數或者作為取位址符、sizeof及typeid等運算子的運算物件時,陣列不會轉換成指向陣列首元素的指標,此時陣列名表示的時是整個陣列比如sizeof(陣列名)得到的是整個陣列的大小。如果使用乙個引用來初始化陣列,陣列也不會轉換成指向陣列首元素的指標。
1.2.2、指標的轉換:常量整數值0或者字面值nullptr能轉換成任意指標型別;指向任意非常量的指標能轉換成void *,反之不行;指向任意物件的指標能轉換成const void *;
1.2.3、轉化成布林型別:存在一種從算術型別或指標型別向布林型別自動轉換的機制。如果指標或算術型別的值為0,轉換結 果是false;否則轉換結果是true。
1.2.4、允許將指向非常量型別的指標轉換成指向相應的常量型別的指標。相反的轉換則不存在。
1.2.5、類型別定義的轉換:類型別能定義由編譯器自動執行的轉換,不過編譯器每次只能執行一種類型別的轉換。
1.3、 顯示轉換
強制型別轉換形式如下:
cast-name(expression);
1.3.1、static_cast:任何具有明確定義的型別轉換,只要不包含底層const,都可以使用static_cast。
(1) 當需要把乙個較大的算術型別賦值給較小的型別時,static_cast非常有用。此時,強制型別轉換告訴程式的讀者和編譯器:我們知道並且不在乎潛在的精度損失。一般來說,如果編譯器發現乙個較大的算術型別試圖賦值給較小的型別,就會給出警告資訊;但是當我們執行了顯示的型別轉換之後,警告資訊就會關閉。
(2) static_cast對於編譯器無法自動執行的型別轉換也非常有用。如下
void* p = &d;
double* dp = static_cast(p); //雖然void*不能自動轉換為type*,但可以通過顯示的強制型別轉換完成
注意雖然能使用static_cast能將void*轉換成其他型別,但是不能使用static_cast進行除此之外指標型別之間的轉換。如下
int *inp;
char *chp = static_cast(inp);//錯誤
1.3. 2、const_cast:
(1) 只能改變運算物件的底層const。
(2) 只有const_cast能改變表示式的常量屬性。使用其他形式的命名強制型別轉換改變表示式的常量屬性都將引發編譯器錯誤。如下:
const char *cp;
char *q = static_cast(cp); //錯誤:static_cast不能轉換掉const性質
static_cast(cp); //正確:字串字面值轉換成string型別
const_cast(cp);//錯誤:const_cast只能改變常量屬性
1.3. 3、reinterpret_cast:通常為運算物件的位模式提供較低層次上的重新解釋。如下
int *ip;
char *pc = reinterpret_cast(ip);
注意pc指向的真實物件是乙個int而非字元。如果把pc當成普通的字元指標使用可能在執行時發生錯誤。如
string str(pc);
因為我們使用了reinterpret_cast將int的位址初始化pc,所以編譯器在轉換之後會認為pc是char*型別的(編譯器無法知道pc實際存放的是指向int的指標)。因此使用pc初始化str可能會導致錯誤。
1.3. 4、dynamic_cast:支援動態型別轉換
1、使用形式如下:
dynamic_cast(e);//e必須是乙個有效的指標
dynamic_cast(e);//e必須是乙個左值
dynamic_cast(e);//e不能是左值
對於以上三種形式,type必須是乙個類型別,並且通常情況下應該含有虛函式。而且e的型別必須滿足以下三個條件中的任意乙個。
(1) e的型別是目標型別type的公有派生類
(2) e的型別是目標型別type的公有基類
(3) e的型別就是目標型別type的型別
如果一條dynamic_cast語句執行得轉化目標是指標型別並且失敗了,則結果為0。如果轉換目標是引用型別並且失敗了,則dynamic_cast運算子將丟擲乙個bad_cast異常。
2、例如:假定base類至少含有乙個虛函式,dervied是base的公有派生類,指標bp指向base。
if(derived *dp = dynamic_cast(bp))
else
將baed*型別的指標bp轉換成derived*,如果轉換成功dp就指向derived物件,執行的就是if語句內部使用derived操作的**。如果 失敗,就執行else語句塊中相應的base操作。這樣做的好處是同時完成型別轉換和條件檢查。並且dp在if語句外部是不可訪問的,這 樣即使轉換失敗,後續的**即使沒有作相應的判斷也不會接觸到這個未繫結的指標。
3、例如:和2一樣
void func(const base &b)
catch(bad_cast)
對引用的dynamic_cast和指標的不同在於當引用型別轉換失敗時,程式丟擲乙個名為std::bad_cast的異常,該異常定義在typeinfo 標準庫標頭檔案中。
1.3.5 雖然有時候不得不使用強制型別轉換,但這種方法本質上是十分危險的。
C 中的型別轉換大總結
使用c 乙個最常見的問題便是各種型別間的轉換。c 中型別轉換的有兩種,轉換和convert轉換。我想知道的是這兩個轉換的區別 還有就是 轉換我用了發現好多不能轉換過來,但是convert是萬能轉換的,那什麼時候該用 什麼時候該用convert呢?最後問下子,把int sum 怎麼用 轉換成float...
C 型別轉換總結
c風格的強制型別轉換 type cast 很簡單,不管什麼型別的轉換統統是 type b type a。c 風格的型別轉換提供了4種型別轉換操作符來應對不同場合的應用。const cast,字面上理解就是去const屬性。static cast,命名上理解是靜態型別轉換。如int轉換成char。dy...
C 型別轉換總結
c風格的強制型別轉換 type cast 很簡單,不管什麼型別的轉換統統是 type b type a。c 風格的型別轉換提供了4種型別轉換操作符來應對不同場合的應用。看似問題複雜化了,其實不然。c風格的型別轉換在程式語句中難以識 c風格的強制型別轉換 type cast 很簡單,不管什麼型別的轉換...