您好,登錄后才能下訂單哦!
我們之前在 C 語(yǔ)言進(jìn)行類型轉(zhuǎn)換是強(qiáng)制類型轉(zhuǎn)換的,這樣極易出 bug,還不易查找。格式如下:(Type)(Experssion) 或 Type(Experssion),我們來(lái)看個(gè)示例代碼,看看 C 語(yǔ)言中的強(qiáng)制類型轉(zhuǎn)換
#include <stdio.h> typedef void(PF)(int); struct Point { int x; int y; }; int main(int argc, char *argv[]) { int v = 0x12345; PF* pf = (PF*)v; char c = char(v); Point* p = (Point*)v; pf(5); printf("p->x = %d\n", p->x); printf("p->y = %d\n", p->y); return 0; }
編譯結(jié)果如下
我們看到直接運(yùn)行段錯(cuò)誤,但是它編譯是通過(guò)的,因此我們?nèi)绻诖笮偷捻?xiàng)目中是難以查找 bug 的。
在 C 方式的強(qiáng)制類型轉(zhuǎn)換的過(guò)程中,它存在的問(wèn)題:a> 過(guò)于粗暴:任意類型之間都可以進(jìn)行轉(zhuǎn)換,編譯器很難判斷其正確性;b> 難于定位:在源碼中無(wú)法快速定位所有使用強(qiáng)制類型轉(zhuǎn)換的語(yǔ)句。那么強(qiáng)制類型轉(zhuǎn)換在實(shí)際工程中是很難完全避免的!如何進(jìn)行更加安全可靠的轉(zhuǎn)換呢?在 C++ 中出現(xiàn)了新式類型轉(zhuǎn)換,C++ 將強(qiáng)制類型轉(zhuǎn)換分為 4 中不同的類型:a> static_cast;b> const_cast;c> dynamic_cast;d> reinterpret_cast;用法是:xxx_cast<Type>(Expression)。下來(lái)我們分別來(lái)講下這四種新式類型轉(zhuǎn)換的特點(diǎn)及要求
A、static_cast 強(qiáng)制類型轉(zhuǎn)換
用于基本類型間的轉(zhuǎn)換;不能用于基本類型指針間的轉(zhuǎn)換;用于有繼承關(guān)系類對(duì)象之間的轉(zhuǎn)換和類指針之間的轉(zhuǎn)換。
B、const_cast 強(qiáng)制類型轉(zhuǎn)換
用于去除變量的只讀屬性;強(qiáng)制轉(zhuǎn)換的目標(biāo)類型必須是指針或引用。
C、reinterpret_cast 強(qiáng)制類型轉(zhuǎn)換
用于指針類型間的強(qiáng)制轉(zhuǎn)換;用于整數(shù)和指針類型間的強(qiáng)制轉(zhuǎn)換。
D、dynamic_cast 強(qiáng)制類型轉(zhuǎn)換
用于有繼承關(guān)系的類指針間的轉(zhuǎn)換;用于有交叉關(guān)系的類指針間的轉(zhuǎn)換;具有類型檢查的功能;需要虛函數(shù)的支持。
關(guān)于上面講到的有些概念,我們會(huì)在后面進(jìn)行詳細(xì)的介紹,下來(lái)我們以代碼為例進(jìn)行分析
#include <stdio.h> void static_cast_demo() { int i = 0x12345; char c = 'c'; int* pi = &i; char* pc = &c; c = static_cast<char>(i); pc = static_cast<char*>(pi); // error } void const_cast_demo() { const int& j = 1; int& k = const_cast<int&>(j); const int x = 2; int& y = const_cast<int&>(x); int z = const_cast<int>(x); // error k = 5; printf("k = %d\n", k); printf("j = %d\n", j); y = 8; printf("x = %d\n", x); printf("y = %d\n", y); printf("&x = %p\n", &x); printf("&y = %p\n", &y); } void reinterpret_cast_demo() { int i = 0; char c = 'c'; int* pi = &i; char* pc = &c; pc = reinterpret_cast<char*>(pi); pi = reinterpret_cast<int*>(pc); pi = reinterpret_cast<int*>(i); c = reinterpret_cast<char>(i); // error } void dynamic_cast_demo() { int i = 0; int* pi = &i; char* pc = dynamic_cast<char*>(pi); // error } int main() { static_cast_demo(); const_cast_demo(); reinterpret_cast_demo(); dynamic_cast_demo(); return 0; }
我們來(lái)分析下這個(gè)代碼,在 static_cast_demo 中,static_cast 不能用于指針間的轉(zhuǎn)換,所以第 11 行會(huì)報(bào)錯(cuò)。在 const_cast_demo 中,第 16 行定義了一個(gè)具有只讀屬性的變量 j,我們還是可以通過(guò) const_cast 來(lái)改變它的屬性的。第 19 行定義了一個(gè)真正意義上的常量,它會(huì)進(jìn)入到符號(hào)表中,但在棧上會(huì)為它分配 4 個(gè)字節(jié)的空間,所以第 20 行的也會(huì)成功。const_cast 強(qiáng)制轉(zhuǎn)換的目標(biāo)類型必須是指針或引用,所以第 22 行會(huì)報(bào)錯(cuò)。第 26 、 27 行會(huì)打印出 5、5;第 31 - 34 會(huì)打印出 2、8、后面兩個(gè)地址是一樣的。在 reinterpret_cast_demo 中,reinterpret_cast 用于指針類型間及整數(shù)和指針類型間的強(qiáng)制轉(zhuǎn)換,所以第 47 行會(huì)報(bào)錯(cuò)。在 dynamic_cast_demo 中,第 54 行會(huì)報(bào)錯(cuò)。我們來(lái)看看編譯結(jié)果
我們分別注釋掉這幾行,再來(lái)編譯,看看結(jié)果是否如我們所分析的那樣
我們看到和我們所分析的是一致的。通過(guò)對(duì)強(qiáng)制類型轉(zhuǎn)換的學(xué)習(xí),總結(jié)如下:1、C 方式的強(qiáng)制類型轉(zhuǎn)換:a> 過(guò)于粗暴。 b> 潛在的問(wèn)題不易被發(fā)現(xiàn)。 c> 不易在代碼中定位;2、新式類型轉(zhuǎn)換以 C++ 關(guān)鍵字的方式出現(xiàn):a> 編譯器能幫助檢查潛在的問(wèn)題。 b> 非常方便的在代碼中定位。 c> 支持動(dòng)態(tài)類型識(shí)別(dynamic_cast)。
歡迎大家一起來(lái)學(xué)習(xí) C++ 語(yǔ)言,可以加我QQ:243343083。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。