C++語(yǔ)言基礎(chǔ)(1):類型轉(zhuǎn)換

相關(guān)章節(jié)

「C++類的特殊成員函數(shù)(1):構(gòu)造函數(shù)」中“3 隱式類類型轉(zhuǎn)換”


考慮下面的例子:

int ival = 0;
ival = 3.541 + 3;   //編譯器會(huì)給出警告

在計(jì)算ival的值時(shí)了袁,C++不會(huì)把兩個(gè)不同類型的值直接相加乏冀,而是提供了一套轉(zhuǎn)換規(guī)則派哲,在做加法計(jì)算前瓣铣,先將兩個(gè)操作數(shù)轉(zhuǎn)換為同一種數(shù)據(jù)類型

這里ival最終的值為6续镇。在賦值操作中岂丘,不可能更改左操作數(shù)對(duì)象的類型陵究。如果賦值操作符的左右操作數(shù)類型不同,那么右操作數(shù)會(huì)被轉(zhuǎn)換為左操作數(shù)的類型奥帘。

在本例中铜邮,從double類型轉(zhuǎn)換為int的過程中,會(huì)導(dǎo)致精度損失寨蹋,大多數(shù)編輯器會(huì)給出警告

warning: assignment to 'int' from 'double'

在上面的過程中松蒜,為了確保表達(dá)式本身的合法性,編譯器對(duì)操作數(shù)的類型按照一定的規(guī)則進(jìn)行了轉(zhuǎn)換已旧。這些轉(zhuǎn)換規(guī)則由編譯器自動(dòng)執(zhí)行秸苗,無需開發(fā)人員介入——有時(shí)甚至不需要開發(fā)人員了解。這種轉(zhuǎn)換過程运褪,我們稱之為隱式類型轉(zhuǎn)換implicit type conversion)惊楼。

此外玖瘸,由開發(fā)人員通過編碼的方式進(jìn)行的類型轉(zhuǎn)換,我們稱之為顯示轉(zhuǎn)換檀咙,也叫強(qiáng)制類型轉(zhuǎn)換cast)店读。

雖然有時(shí)候確實(shí)需要強(qiáng)制類型轉(zhuǎn)換,但是它們本質(zhì)上是非常危險(xiǎn)的攀芯。

如果兩個(gè)類型之間可以相互轉(zhuǎn)換conversion),則稱這兩個(gè)類型相關(guān)文虏。

下面我們分別對(duì)這兩種轉(zhuǎn)換方式進(jìn)行深入的介紹:

1 隱式類型轉(zhuǎn)換

為了理解隱式類型轉(zhuǎn)換侣诺,我們需要知道它們?cè)谑裁磿r(shí)候發(fā)生,以及可能出現(xiàn)哪些類型的轉(zhuǎn)換氧秘。

1.1 何時(shí)發(fā)生隱式類型轉(zhuǎn)換

  • 在混合類型的表達(dá)式中年鸳,其操作數(shù)被轉(zhuǎn)換為相同的類型;
  • 用作條件的表達(dá)式被轉(zhuǎn)換為bool類型丸相;
  • 用一表達(dá)式初始化某個(gè)變量搔确,或?qū)⒁槐磉_(dá)式賦值給某個(gè)變量,則該表達(dá)式被轉(zhuǎn)換為該變量類型灭忠;
  • 在函數(shù)調(diào)用傳遞實(shí)參的過程中膳算,其操作數(shù)被轉(zhuǎn)換為形參的類型。

第一點(diǎn)和第三點(diǎn)已經(jīng)在上面的例子中有過說明弛作,下面我們針對(duì)第二點(diǎn)和第四點(diǎn)舉例說明:

bool func(int ival)
{
    bool flag = false;
    if (ival)   //ival轉(zhuǎn)換為bool類型涕蜂,上述第二點(diǎn)
    {
        flag = true;
    }
    return flag;
}

int main()
{
    double dval = 3.541;
    func(dval); //dval轉(zhuǎn)換為int類型,上述第四點(diǎn)
    return 1;
}

1.2 隱式類型轉(zhuǎn)換的種類和規(guī)則

1.2.1 算數(shù)轉(zhuǎn)換(arithmetic conversion)

算數(shù)轉(zhuǎn)換映琳,保證在執(zhí)行操作數(shù)之前机隙,將二元操作符(如算數(shù)和邏輯操作符)的兩個(gè)操作數(shù)轉(zhuǎn)換為同一類型,并使表達(dá)式的值也具有相同的類型萨西。

算數(shù)轉(zhuǎn)換規(guī)則的核心有鹿,是保護(hù)計(jì)算值的精度不降低。在規(guī)則的內(nèi)容中谎脯,定義了一個(gè)類型轉(zhuǎn)換的層次葱跋,該層次規(guī)定了操作數(shù)應(yīng)按什么次序轉(zhuǎn)換為表達(dá)式中最寬的類型

由于要保證計(jì)算值的精度穿肄,因此這類轉(zhuǎn)換本質(zhì)上依賴于機(jī)器對(duì)各數(shù)據(jù)類型的具體實(shí)現(xiàn)年局。

整形提升integer promotion)規(guī)則:對(duì)于所有比int小的整形,包括char咸产、signed char矢否、unsigned char、short和unsigned short脑溢,如果該類型的所有可能的值都能包容在int內(nèi)僵朗,它們就會(huì)被提升為int型赖欣,否則,它們將被提升為unsigned int验庙。

如果將bool值提升為int顶吮,則false轉(zhuǎn)化為0,而true則轉(zhuǎn)化為1粪薛。

下面通過例子悴了,我們可以理解的更透徹:

bool flag;
char cval;
short sval;
unsigned short usval;
int ival;
unsigned int uival;
long lval;
unsigned long ulval;
float fval;
double dval;
3.14159L + 'a'; //'a'轉(zhuǎn)換為int,而后再轉(zhuǎn)換為double long
dval + ival;    //ival轉(zhuǎn)換為double
dval + fval;    //fval轉(zhuǎn)換為double
ival = dval;    //dval轉(zhuǎn)換為int(截?cái)啵?flag = dval;    //如果dval是0违寿,那么flag為false湃交,否則為true
cval + fval;    //cval轉(zhuǎn)換為int,而后再轉(zhuǎn)換為float
sval + cval;    //sval和cval都轉(zhuǎn)換為int
cval + lval;    //cval轉(zhuǎn)換為long
ival + ulval;   //ival轉(zhuǎn)換為unsigned long
usval + ival;   //轉(zhuǎn)換取決于unsigned short和int的位寬
uival + lval;   //轉(zhuǎn)換取決于unsigned int和long的位寬

最后兩條語(yǔ)句藤巢,單獨(dú)說明一下搞莺。為了保證計(jì)算值的精度不降低,倒數(shù)第二條掂咒,如果int型足夠表示所有unsigned short型的值才沧,則將unsigned short轉(zhuǎn)換為int,否則绍刮,將兩個(gè)操作數(shù)均轉(zhuǎn)換為unsigned int温圆。相同的,對(duì)于最后一條語(yǔ)句孩革,如果long型足夠表示所有unsigned int型的值捌木,則將unsigned int轉(zhuǎn)換為long,否則嫉戚,將兩個(gè)操作數(shù)均轉(zhuǎn)換為unsigned long刨裆。

1.2.2 指針轉(zhuǎn)換

指針轉(zhuǎn)換主要存在于下列幾種情況中:

  • 使用數(shù)組時(shí),大多數(shù)情況下會(huì)將數(shù)組轉(zhuǎn)換為指向第一個(gè)元素的指針彬檀;
  • 指向任意數(shù)據(jù)類型的指針都可轉(zhuǎn)換為void*類型帆啃;
  • 整型數(shù)值常量0可轉(zhuǎn)換為任意指針類型(轉(zhuǎn)換后為空指針)。

對(duì)于第一條窍帝,在下列幾種情況下努潘,不會(huì)進(jìn)行類型轉(zhuǎn)換:

  • 數(shù)組用作取地址操作符(&)的操作數(shù)時(shí);
  • 數(shù)組用作sizeof操作符的操作數(shù)時(shí)坤学;
  • 用數(shù)組對(duì)數(shù)組的引用進(jìn)行初始化時(shí)疯坤。

1.2.3 轉(zhuǎn)換為bool類型

算數(shù)值和指針都可以轉(zhuǎn)換為bool類型。以下幾種情況深浮,轉(zhuǎn)換的bool值為false:

  • 算數(shù)值為0压怠;
  • 指針值為NULL;
  • char型值為空字符(null)菌瘫。

本質(zhì)上蜗顽,上述情況都可以轉(zhuǎn)換為算數(shù)值0。其他情況下雨让,均為true雇盖。

1.2.4 轉(zhuǎn)換與枚舉類型

C++自動(dòng)將枚舉類型的對(duì)象或枚舉成員轉(zhuǎn)換為整型,其轉(zhuǎn)換結(jié)果可用于任何要求使用整數(shù)值的地方栖忠。

將enum對(duì)象或枚舉成員提升為什么類型崔挖,由機(jī)器實(shí)現(xiàn)枚舉成員最大值共同決定,且該類型至少是int庵寞。

1.2.5 轉(zhuǎn)換為const對(duì)象

  • 使用非const對(duì)象初始化const對(duì)象的引用虚汛;
  • 可以將非const對(duì)象的地址(或指針)轉(zhuǎn)換為指向相關(guān)const類型的指針。
int i;
const int &j = i;   //第一種情況

int ci = 0;
const int *p = &ci; //第二種情況

1.2.6 由標(biāo)準(zhǔn)庫(kù)類型定義的轉(zhuǎn)換

類類型可以定義由編譯器自動(dòng)執(zhí)行的類型轉(zhuǎn)換皇帮。該部分超出本章的討論范圍,將會(huì)在C++類的介紹中進(jìn)行描述蛋辈。

2 強(qiáng)制類型轉(zhuǎn)換

建議:避免使用強(qiáng)制類型轉(zhuǎn)換属拾,因?yàn)槠潢P(guān)閉或掛起了正常的類型檢查。

2.1 何時(shí)需要強(qiáng)制類型轉(zhuǎn)換

  • 覆蓋通常的標(biāo)準(zhǔn)轉(zhuǎn)換冷溶;
  • 可能存在多種轉(zhuǎn)換時(shí)渐白,需要選擇一種特定的轉(zhuǎn)換類型。

2.2 命名的強(qiáng)制類型轉(zhuǎn)換

其一般形式如下:

cast-name<type>(expression);
  • cast-name為static_cast逞频、dynamic_cast纯衍、const_cast和reinterpret_cast之一;
  • type為轉(zhuǎn)換的類型目標(biāo)苗胀;
  • expression為被強(qiáng)制轉(zhuǎn)換的值襟诸。

強(qiáng)制轉(zhuǎn)換的類型,指定了在expression上執(zhí)行某種特定類型的轉(zhuǎn)換:

2.2.1 dynamic_cast

支持運(yùn)行時(shí)識(shí)別指針或引用所指向的對(duì)象基协。

2.2.2 const_cast

顧名思義歌亲,可以轉(zhuǎn)換掉表達(dá)式的const性質(zhì)。例如:

const char *pc_str;
char* pc = string_copy(const_cast<char*>(pc_str));

這里澜驮,假設(shè)有函數(shù)string_copy陷揪,我們對(duì)其唯一的char* 類型參數(shù)只讀不寫。當(dāng)我們要傳入的實(shí)參是const char* 類型時(shí)杂穷,可以通過const_cast轉(zhuǎn)換掉參數(shù)的const性質(zhì)悍缠。

2.2.3 static_cast

編譯器隱式執(zhí)行的任何類型轉(zhuǎn)換都可以有static_cast顯示完成;如果編譯器不提供自動(dòng)轉(zhuǎn)換耐量,也可以通過static_cast來實(shí)現(xiàn)飞蚓。

//前一種情況
double d = 97.0;
char ch = static_cast<char>(d); //編譯器不再報(bào)精度丟失的錯(cuò)誤

//后一種情況
void* p = &d;
double *dp = static_cast<double*>(p);

2.2.4 reinterpret_cast

通常為操作數(shù)的位模式提供較低層次的重新解釋廊蜒。

int *ip;
char* pc = reinterpret_cast<char*>(ip);

2.3 舊式強(qiáng)制類型轉(zhuǎn)換

在引入命名的強(qiáng)制類型轉(zhuǎn)換操作符之前玷坠,顯示強(qiáng)制轉(zhuǎn)換用圓括號(hào)將類型括起來實(shí)現(xiàn):

type (expression);  //函數(shù)風(fēng)格的強(qiáng)制類型轉(zhuǎn)換寫法
(type) expression;  //C語(yǔ)言風(fēng)格的強(qiáng)制類型轉(zhuǎn)換寫法

與舊式相比較蜗搔,命名的強(qiáng)制類型轉(zhuǎn)換的優(yōu)點(diǎn)是:加強(qiáng)強(qiáng)制類型轉(zhuǎn)換的可視性,開發(fā)人員可清晰辨別每個(gè)強(qiáng)制類型轉(zhuǎn)換潛在的風(fēng)險(xiǎn)級(jí)別八堡。

支持舊式強(qiáng)制轉(zhuǎn)換符號(hào)樟凄,是為了對(duì)“在標(biāo)準(zhǔn)C++之前編寫的程序”保持向后兼容性,并保持與C語(yǔ)言的兼容性兄渺。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缝龄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子挂谍,更是在濱河造成了極大的恐慌叔壤,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件口叙,死亡現(xiàn)場(chǎng)離奇詭異炼绘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)妄田,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門俺亮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人疟呐,你說我怎么就攤上這事脚曾。” “怎么了启具?”我有些...
    開封第一講書人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵本讥,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我鲁冯,道長(zhǎng)拷沸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任薯演,我火速辦了婚禮堵漱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涣仿。我一直安慰自己勤庐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開白布好港。 她就那樣靜靜地躺著愉镰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钧汹。 梳的紋絲不亂的頭發(fā)上丈探,一...
    開封第一講書人閱讀 51,274評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音拔莱,去河邊找鬼碗降。 笑死隘竭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的讼渊。 我是一名探鬼主播动看,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼爪幻!你這毒婦竟也來了菱皆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤挨稿,失蹤者是張志新(化名)和其女友劉穎仇轻,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奶甘,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡篷店,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了臭家。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疲陕。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖侣监,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情臣淤,我是刑警寧澤橄霉,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站邑蒋,受9級(jí)特大地震影響姓蜂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜医吊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一钱慢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卿堂,春花似錦束莫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至穗慕,卻和暖如春饿敲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背逛绵。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工怀各, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留倔韭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓瓢对,卻偏偏與公主長(zhǎng)得像寿酌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子沥曹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容