C++中4種強(qiáng)制類型轉(zhuǎn)換的區(qū)別詳析
前言
C++即支持C風(fēng)格的類型轉(zhuǎn)換,又有自己風(fēng)格的類型轉(zhuǎn)換。C風(fēng)格的轉(zhuǎn)換格式很簡(jiǎn)單,但是有不少缺點(diǎn)的:
1.轉(zhuǎn)換太過(guò)隨意,可以在任意類型之間轉(zhuǎn)換。你可以把一個(gè)指向const對(duì)象的指針轉(zhuǎn)換成指向非const對(duì)象的指針,把一個(gè)指向基類對(duì)象的指針轉(zhuǎn)換成一個(gè)派生類對(duì)象的指針,這些轉(zhuǎn)換之間的差距是非常巨大的,但是傳統(tǒng)的C語(yǔ)言風(fēng)格的類型轉(zhuǎn)換沒(méi)有區(qū)分這些。
2.C風(fēng)格的轉(zhuǎn)換沒(méi)有統(tǒng)一的關(guān)鍵字和標(biāo)示符。對(duì)于大型系統(tǒng),做代碼排查時(shí)容易遺漏和忽略。
C++風(fēng)格完美的解決了上面兩個(gè)問(wèn)題。1.對(duì)類型轉(zhuǎn)換做了細(xì)分,提供了四種不同類型轉(zhuǎn)換,以支持不同需求的轉(zhuǎn)換;2.類型轉(zhuǎn)換有了統(tǒng)一的標(biāo)示符,利于代碼排查和檢視。下面分別來(lái)介紹這四種轉(zhuǎn)換:static_cast、dynamic_cast、const_cast和reinterpre_cast.
一、static_cast轉(zhuǎn)換
1.基本用法:static_cast<type-id> expression
2.使用場(chǎng)景:
a、用于類層次結(jié)構(gòu)中基類和派生類之間指針或引用的轉(zhuǎn)換
上行轉(zhuǎn)換(派生類---->基類)是安全的;
下行轉(zhuǎn)換(基類---->派生類)由于沒(méi)有動(dòng)態(tài)類型檢查,所以是不安全的。
b、用于基本數(shù)據(jù)類型之間的轉(zhuǎn)換,如把int轉(zhuǎn)換為char,這種帶來(lái)安全性問(wèn)題由程序員來(lái)保證
c、把空指針轉(zhuǎn)換成目標(biāo)類型的空指針
d、把任何類型的表達(dá)式轉(zhuǎn)為void類型
3.使用特點(diǎn)
a、主要執(zhí)行非多態(tài)的轉(zhuǎn)換操作,用于代替C中通常的轉(zhuǎn)換操作
b、隱式轉(zhuǎn)換都建議使用static_cast進(jìn)行標(biāo)明和替換
二、dynamic_cast轉(zhuǎn)換
1.基本用法:dynamic_cast<type-id> expression
2.使用場(chǎng)景:只有在派生類之間轉(zhuǎn)換時(shí)才使用dynamic_cast,type-id必須是類指針,類引用或者void*。
3.使用特點(diǎn):
a、基類必須要有虛函數(shù),因?yàn)閐ynamic_cast是運(yùn)行時(shí)類型檢查,需要運(yùn)行時(shí)類型信息,而這個(gè)信息是存儲(chǔ)在類的虛函數(shù)表中,只有一個(gè)類定義了虛函數(shù),才會(huì)有虛函數(shù)表(如果一個(gè)類沒(méi)有虛函數(shù),那么一般意義上,這個(gè)類的設(shè)計(jì)者也不想它成為一個(gè)基類)。
b、對(duì)于下行轉(zhuǎn)換,dynamic_cast是安全的(當(dāng)類型不一致時(shí),轉(zhuǎn)換過(guò)來(lái)的是空指針),而static_cast是不安全的(當(dāng)類型不一致時(shí),轉(zhuǎn)換過(guò)來(lái)的是錯(cuò)誤意義的指針,可能造成踩內(nèi)存,非法訪問(wèn)等各種問(wèn)題)
c、dynamic_cast還可以進(jìn)行交叉轉(zhuǎn)換
三、const_cast轉(zhuǎn)換
1.基本用法:const_cast<type-id>expression
2.使用場(chǎng)景:
a、常量指針轉(zhuǎn)換為非常量指針,并且仍然指向原來(lái)的對(duì)象
b、常量引用被轉(zhuǎn)換為非常量引用,并且仍然指向原來(lái)的對(duì)象
3.使用特點(diǎn):
a、cosnt_cast是四種類型轉(zhuǎn)換符中唯一可以對(duì)常量進(jìn)行操作的轉(zhuǎn)換符
b、去除常量性是一個(gè)危險(xiǎn)的動(dòng)作,盡量避免使用。一個(gè)特定的場(chǎng)景是:類通過(guò)const提供重載時(shí),一般都是非常量函數(shù)調(diào)用const_cast<const T>將參數(shù)轉(zhuǎn)換為常量,然后調(diào)用常量函數(shù),然后得到結(jié)果再調(diào)用const_cast <T>去除常量性。
四、reinterpret_cast轉(zhuǎn)換
1.基本用法:reinterpret_cast<type-id>expression
2.使用場(chǎng)景:不到萬(wàn)不得已,不用使用這個(gè)轉(zhuǎn)換符,高危操作
3.使用特點(diǎn):
a、reinterpret_cast是從底層對(duì)數(shù)據(jù)進(jìn)行重新解釋,依賴具體的平臺(tái),可移植性差
b、reinterpret_cast可以將整型轉(zhuǎn)換為指針,也可以把指針轉(zhuǎn)換為數(shù)組
c、reinterpret_cast可以在指針和引用里進(jìn)行肆無(wú)忌憚的轉(zhuǎn)換
五、各種轉(zhuǎn)換之間的比較
1.static_cast和dynamic_cast
class Base { public: Base(int c = 2):_c(c){} public: int _c; }; class Derived:public Base { public: int _d; int _e; }; int main(void) { int tempA = 2; int tempB = 3; Base base; /*1.無(wú)編譯告警,但是危險(xiǎn)操作,譬如說(shuō)調(diào)用drvPtrA->_d會(huì)造成不可預(yù)知的后果*/ Derived *drvPtrA = static_cast<Derived *>(&base); drvPtrA->_d = 4; drvPtrA->_e = 5; /*2.輸出:tempA為5,tempB為4,踩內(nèi)存了(機(jī)器信息:32位ubuntu,編譯器clang++)*/ cout<<tempA<<endl; cout<<tempB<<endl; /*3.Base中沒(méi)有虛函數(shù),無(wú)法查看運(yùn)行時(shí)信息,編譯不過(guò)*/ Derived *drvPtrB = dynamic_cast<Derived *>(base); return 0; }
在基類派生類互相轉(zhuǎn)換時(shí),雖然static_cast是在編譯期完成,效率更高,但是不安全,上例中就示范了一個(gè)踩內(nèi)存的例子。相比之下因?yàn)閐ynamic_cast可以查看運(yùn)行時(shí)信息,上例如果Base含有虛函數(shù),那么drvPtrB就是一個(gè)空指針(這可比踩內(nèi)存什么的好多了),不能操作Derived中_d的數(shù)據(jù)從而保證安全性,所以應(yīng)該優(yōu)先使用dynamic_cast。
2.static_cast和reinterpret_cast
class BaseA { public: BaseA(int c = 2):_c(c){} int _c; }; class BaseB { public: BaseB(int d = 3):_d(d){} int _d; }; int main(void) { BaseA baseA; /*1.編譯不過(guò)*/ BaseB *baseB = static_cast<BaseB *>(&baseA); /*2.無(wú)任何編譯告警,編譯通過(guò),正常運(yùn)行*/ BaseB *baseC = reinterpret_cast<BaseB *>(&baseA); cout<<baseC->_d<<endl; return 0; }
static_cast雖然也不是一種絕對(duì)安全的轉(zhuǎn)換,但是它在轉(zhuǎn)換時(shí),還是會(huì)進(jìn)行必要的檢測(cè)(諸如指針越界計(jì)算,類型檢查)。reinterpret_cast完全是肆無(wú)忌憚,直接從二進(jìn)制開(kāi)始重新映射解釋,是極度不安全的,再次提醒,不到萬(wàn)不得已,不要使用。
總結(jié)
到此這篇關(guān)于C++中4種強(qiáng)制類型轉(zhuǎn)換區(qū)別的文章就介紹到這了,更多相關(guān)C++強(qiáng)制類型轉(zhuǎn)換區(qū)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C++中四種強(qiáng)制轉(zhuǎn)換方式的區(qū)別
- C++超詳細(xì)講解強(qiáng)制類型轉(zhuǎn)換
- C++強(qiáng)制類型轉(zhuǎn)換的四種方式
- C++ 強(qiáng)制類型轉(zhuǎn)換詳解
- C++強(qiáng)制類型轉(zhuǎn)換(static_cast、dynamic_cast、const_cast、reinterpret_cast)
- 關(guān)于C++的強(qiáng)制類型轉(zhuǎn)換淺析
- C++中4種強(qiáng)制類型轉(zhuǎn)換的區(qū)別總結(jié)
- C++中四種強(qiáng)制轉(zhuǎn)換的實(shí)現(xiàn)方法與區(qū)別
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)停車場(chǎng)項(xiàng)目
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)停車場(chǎng)項(xiàng)目,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03C語(yǔ)言實(shí)現(xiàn)矩陣翻轉(zhuǎn)(上下翻轉(zhuǎn)、左右翻轉(zhuǎn))
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)矩陣翻轉(zhuǎn)(上下翻轉(zhuǎn)、左右翻轉(zhuǎn))的相關(guān)資料,需要的朋友可以參考下2017-05-05基于C語(yǔ)言代碼實(shí)現(xiàn)點(diǎn)餐系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了基于C語(yǔ)言代碼實(shí)現(xiàn)點(diǎn)餐系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-01-01C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)中串的模式匹配
這篇文章主要介紹了C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)中串的模式匹配的相關(guān)資料,需要的朋友可以參考下2017-05-05C++構(gòu)造函數(shù)和析構(gòu)函數(shù)的使用與講解
今天小編就為大家分享一篇關(guān)于C++構(gòu)造函數(shù)和析構(gòu)函數(shù)的使用與講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12深入解析C語(yǔ)言中的內(nèi)存分配相關(guān)問(wèn)題
這篇文章主要深入地介紹了C語(yǔ)言中的內(nèi)存分配,C語(yǔ)言編程中的內(nèi)存泄漏問(wèn)題一直以來(lái)都是C編程中的一大棘手問(wèn)題,本文從malloc和指針等方面對(duì)C內(nèi)存進(jìn)行了深層次講解,強(qiáng)烈推薦!需要的朋友可以參考下2015-08-08