C++ 类型转换 :C语言的类型转换、C++的四种强制类型转换、explicit
文章目錄
- C語(yǔ)言中的類(lèi)型轉(zhuǎn)換
- 隱式類(lèi)型轉(zhuǎn)換
- 顯式類(lèi)型轉(zhuǎn)換
- C++ 強(qiáng)制類(lèi)型轉(zhuǎn)換
- static_cast
- reinterpret_cast
- const_cast
- dynamic_cast
- explicit
C語(yǔ)言中的類(lèi)型轉(zhuǎn)換
C語(yǔ)言中的類(lèi)型轉(zhuǎn)換,通常發(fā)生在傳參時(shí)參數(shù)類(lèi)型不匹配,又或是接收的返回值類(lèi)型不一致、賦值雙方類(lèi)型不同的情景,就會(huì)需要用到類(lèi)型轉(zhuǎn)換。主要分為隱式類(lèi)型轉(zhuǎn)換與顯示類(lèi)型轉(zhuǎn)換兩種。
隱式類(lèi)型轉(zhuǎn)換
編譯器在編譯階段自動(dòng)進(jìn)行,通常適用于相近的類(lèi)型,如果不能轉(zhuǎn)換則會(huì)編譯失敗。
例如:
顯式類(lèi)型轉(zhuǎn)換
需要用戶(hù)自己處理,通常用于不相近類(lèi)型的轉(zhuǎn)換。
如:
從上面可以看出來(lái),C語(yǔ)言的類(lèi)型轉(zhuǎn)換使用起來(lái)很簡(jiǎn)單,但是也有很大的缺點(diǎn)。
C++ 強(qiáng)制類(lèi)型轉(zhuǎn)換
標(biāo)準(zhǔn)C++為了加強(qiáng)類(lèi)型轉(zhuǎn)換的可視性,引入了四種命名的強(qiáng)制類(lèi)型轉(zhuǎn)換操作符:static_cast、reinterpret_cast、const_cast、dynamic_cast
static_cast
static_cast用于非多態(tài)類(lèi)型的轉(zhuǎn)換(靜態(tài)轉(zhuǎn)換),編譯器隱式執(zhí)行的任何類(lèi)型轉(zhuǎn)換都可用static_cast,但它不能用于兩個(gè)不相關(guān)的類(lèi)型進(jìn)行轉(zhuǎn)換。(即對(duì)應(yīng)C語(yǔ)言中的隱式類(lèi)型轉(zhuǎn)換)
int main() {double d = 1.9;int i = static_cast<int>(d);cout << i; }reinterpret_cast
reinterpret_cast是一種較為危險(xiǎn)的類(lèi)型轉(zhuǎn)換,通常為操作數(shù)的位模式提供較低層次的重新解釋,用于將一種類(lèi)型轉(zhuǎn)換為另一種不同的類(lèi)型,通常適用于指針、引用、以及整數(shù)之間的類(lèi)型轉(zhuǎn)換。
int main() {int i = 9;int* p = &i;double* p2 = reinterpret_cast<double*>(p);cout << *p2 << ' ' << *p; }
如上面所說(shuō),這種轉(zhuǎn)換十分容易導(dǎo)致錯(cuò)誤的發(fā)生,因?yàn)橹羔橆?lèi)型其實(shí)是其指向的地址的類(lèi)型,決定了指針看待這段地址的方式,它該如何讀取數(shù)據(jù)。這里我把int改成了double,使得他原本應(yīng)該讀取4個(gè)字節(jié),而變成了8個(gè)字節(jié),就導(dǎo)致了數(shù)據(jù)的變化。如果使用不當(dāng)很容易會(huì)造成越界訪問(wèn)導(dǎo)致程序崩潰。
const_cast
const_cast通常用于刪除變量的const屬性
如果想要修改const變量的值,就需要用volatile來(lái)取消編譯器優(yōu)化。因?yàn)閏onst變量創(chuàng)建后會(huì)被放入寄存器中,只有我們?nèi)onst變量的地址時(shí),他才會(huì)在內(nèi)存中申請(qǐng)空間,而我們修改的是const變量在內(nèi)存中的值,但是由于編譯器優(yōu)化,當(dāng)使用const變量時(shí)就會(huì)到寄存器中去取值,所以需要用volatile取消編譯器優(yōu)化,讓其每次在內(nèi)存中取值。
不加volatile時(shí)
int main() {const int ci = 10;int* pi = const_cast<int*>(&ci); // 對(duì)應(yīng)c語(yǔ)言強(qiáng)制類(lèi)型轉(zhuǎn)換中去掉const屬性的(不相近類(lèi)型)*pi = 20;cout << ci << ' ' << *pi; }
加volatile時(shí)
dynamic_cast
dynamic_cast是一種動(dòng)態(tài)的類(lèi)型轉(zhuǎn)換,是C++新增的概念,用于將一個(gè)父類(lèi)對(duì)象的指針/引用轉(zhuǎn)換為子類(lèi)對(duì)象的指針或引用。
派生類(lèi)可以賦值給基類(lèi)的對(duì)象、指針或者引用,這樣的賦值也叫做對(duì)象切割。
例如Human類(lèi)和Student類(lèi)
從這幅圖可以看出來(lái),當(dāng)把派生類(lèi)賦值給基類(lèi)時(shí),可以通過(guò)切割掉多出來(lái)的成員如_stuNum的方式來(lái)完成賦值。
但是基類(lèi)對(duì)象如果想賦值給派生類(lèi),則不可以,因?yàn)樗荒軕{空多一個(gè)_stuNum成員出來(lái)。
但是基類(lèi)的指針或者引用卻可以強(qiáng)制類(lèi)型轉(zhuǎn)換賦值給派生類(lèi)對(duì)象, 如:
這個(gè)過(guò)程有可能成功,也有可能會(huì)因?yàn)樵浇鐚?dǎo)致出現(xiàn)問(wèn)題。 如果使用C語(yǔ)言的強(qiáng)制類(lèi)型轉(zhuǎn)換,很可能就會(huì)出現(xiàn)問(wèn)題,因?yàn)槠錄](méi)有安全保障。而如果使用dynamic_cast,則能夠保證安全,因?yàn)槠鋾?huì)先檢查轉(zhuǎn)換是否能夠成功,如果不能成功則返回0,能則直接轉(zhuǎn)換。
但是dynamic_cast的向下轉(zhuǎn)換只支持繼承中的多態(tài)類(lèi)型,也就是父類(lèi)之中必須包含虛函數(shù)。
int main() {Human h1;Student s1;Human* hPtr1 = &s1;//指向派生類(lèi)對(duì)象Human* hPtr2 = &h1;//指向基類(lèi)對(duì)象//傳統(tǒng)方法Student* pPtr = (Student*)hPtr1;//沒(méi)問(wèn)題Student* pPtr = (Student*)hPtr2;//有時(shí)候沒(méi)有問(wèn)題,但是會(huì)存在越界風(fēng)險(xiǎn)//dynamic_castStudent* pPtr = dynamic_cast<Student*>(hPtr2);return 0; }注意:
dynamic_cast是如何識(shí)別父類(lèi)的指針指向的是父類(lèi)對(duì)象還是子類(lèi)對(duì)象的呢?其原理就是在運(yùn)行時(shí)通過(guò)查找虛函數(shù)表上面的標(biāo)識(shí)信息,來(lái)確認(rèn)其指向的到底是父類(lèi)還是子類(lèi),這也就是為什么只能用于含有虛函數(shù)的類(lèi)。
這種在運(yùn)行中進(jìn)行類(lèi)型識(shí)別的方法,也叫做RTTI,C++中有很多支持RTTI的方法,如dynamic_cast,typeid,decltype
explicit
explicit關(guān)鍵字主要用來(lái)阻止轉(zhuǎn)換構(gòu)造函數(shù)而進(jìn)行隱式類(lèi)型轉(zhuǎn)換的發(fā)生
class Date { public:Date(int year = 0, int month = 4, int day = 24):_year(year),_month(month),_day(day){}int _year;int _month;int _day; };int main() {Date d1(2020, 4, 24);Date d2 = 2020;//C++98Date d3 = { 2020, 4 }; //C++11Date d4 = { 2020, 4, 24 }; //C+11 }對(duì)于這里的d2,我們用2020給它賦值,而d3和d4分別用了列表來(lái)給它賦值,并且這四個(gè)對(duì)象它們最后的值是一模一樣的,那是為什么呢?這里的2020明明是一個(gè)整型,d3和d4是一個(gè)列表,為什么能夠給對(duì)象賦值呢?
這里就牽扯到了隱式的類(lèi)型轉(zhuǎn)換
這里其實(shí)是先用這個(gè)整型值來(lái)調(diào)用了全缺省的構(gòu)造函數(shù)來(lái)創(chuàng)建了一個(gè)臨時(shí)對(duì)象,再使用這個(gè)對(duì)象來(lái)為d2,d3,d4賦值。
這是一種很容易引起誤會(huì)的寫(xiě)法,所以c++提供了關(guān)鍵字explicit,用這個(gè)關(guān)鍵字修飾的函數(shù)就會(huì)禁止隱式類(lèi)型的轉(zhuǎn)化
這時(shí)這種隱式類(lèi)型轉(zhuǎn)換就不會(huì)發(fā)生了
總結(jié)
以上是生活随笔為你收集整理的C++ 类型转换 :C语言的类型转换、C++的四种强制类型转换、explicit的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C++ 智能指针 :内存泄漏、 RAII
- 下一篇: Linux网络编程 | 多路复用I/O