建設(shè)電子商務(wù)網(wǎng)站目的指數(shù)平滑法
目錄
C語言中的類型轉(zhuǎn)換
C++強制類型轉(zhuǎn)換
static_cast
reinterpret_cast
?const_cast
?dynamic_cast
延伸問題?
?RTTI(了解)
?
C語言中的類型轉(zhuǎn)換
?在C語言中,如果賦值運算符左右兩側(cè)類型不同,或者形參與實參類型不匹配,或者返回值類型與
接收返回值類型不一致時,就需要發(fā)生類型轉(zhuǎn)化,C語言中總共有兩種形式的類型轉(zhuǎn)換:隱式類型
轉(zhuǎn)換和顯式類型轉(zhuǎn)換。
1. 隱式類型轉(zhuǎn)化:編譯器在編譯階段自動進(jìn)行,能轉(zhuǎn)就轉(zhuǎn),不能轉(zhuǎn)就編譯失敗
2. 顯式類型轉(zhuǎn)化:需要用戶自己處理
void Test ()
{
int i = 1;
// 隱式類型轉(zhuǎn)換
double d = i;
printf("%d, %.2f\n" , i, d);
int* p = &i;
// 顯示的強制類型轉(zhuǎn)換
int address = (int) p;
printf("%x, %d\n" , p, address);
}
缺陷:
轉(zhuǎn)換的可視性比較差,所有的轉(zhuǎn)換形式都是以一種相同形式書寫,難以跟蹤錯誤的轉(zhuǎn)換
C++強制類型轉(zhuǎn)換
?標(biāo)準(zhǔn)C++為了加強類型轉(zhuǎn)換的可視性,引入了四種命名的強制類型轉(zhuǎn)換操作符:
static_cast、reinterpret_cast、const_cast、dynamic_cast
static_cast
?static_cast用于非多態(tài)類型的轉(zhuǎn)換(靜態(tài)轉(zhuǎn)換),編譯器隱式執(zhí)行的任何類型轉(zhuǎn)換都可用
static_cast,但它不能用于兩個不相關(guān)的類型進(jìn)行轉(zhuǎn)換。用于意義相近的類型。
注意這里的格式,尤其是括號的位置。
?C語言中可以這樣轉(zhuǎn)換,而C++?static_cast卻不行,因為?static_cast主要是用做隱式類型的轉(zhuǎn)換,C語言中把這種轉(zhuǎn)換叫強制類型轉(zhuǎn)換
這種不相關(guān)的類型應(yīng)該用?reinterpret_cast來進(jìn)行轉(zhuǎn)換
reinterpret_cast
?reinterpret_cast操作符通常為操作數(shù)的位模式提供較低層次的重新解釋,用于將一種類型轉(zhuǎn)換
為另一種不同的類型
?const_cast
?const_cast最常用的用途就是刪除變量的const屬性,方便賦值。
這里把const int *轉(zhuǎn)為int *,這樣可以間接修改a,如果直接修改a會報錯,這里的a并沒有被放到常量區(qū),而是在棧上,我們可以通過拿到a的地址對a進(jìn)行修改。
我們可以看到a是2,*p是3?
調(diào)試窗口下倆個卻都是3,這是因為a確實在內(nèi)存中被修改成了3,但是編譯器在讀取a的時候不一定去內(nèi)存中去讀取,而是在寄存器中讀取,雖然內(nèi)存中是3,但寄存器中是2,所以這里會打印2
如果想去讀取內(nèi)存中的a,我們加關(guān)鍵字?volatile
注:所有的轉(zhuǎn)換都會產(chǎn)生臨時變量,臨時變量具有常性。?
這里發(fā)生了隱式類型轉(zhuǎn)換,如果要對其進(jìn)行引用就要加const,因為臨時變量具有常性
?dynamic_cast
dynamic_cast用于將一個父類對象的指針/引用轉(zhuǎn)換為子類對象的指針或引用(動態(tài)轉(zhuǎn)換)
向上轉(zhuǎn)型:子類對象指針/引用->父類指針/引用(不需要轉(zhuǎn)換,賦值兼容規(guī)則)
向上轉(zhuǎn)不是隱式類型轉(zhuǎn)換,這是語法天然支持的
向下轉(zhuǎn)型:父類對象指針/引用->子類指針/引用(用dynamic_cast轉(zhuǎn)型是安全的),子類指針/引用轉(zhuǎn)子類指針/引用是安全的,子類指針/引用轉(zhuǎn)父類指針/引用是不安全的
注意:
1. dynamic_cast只能用于父類含有虛函數(shù)的類
2. dynamic_cast會先檢查是否能轉(zhuǎn)換成功,能成功則轉(zhuǎn)換,不能則返回0
?注意父類對象無論如何都不允許轉(zhuǎn)為子類對象
?父類指針有可能指向父類,也有可能指向子類,這里fun函數(shù)形參pa可能指向父類也可能指向子類,如果pa指向父類,我們將其轉(zhuǎn)換成子類此時會有風(fēng)險,父類只有_a,父類指針只能訪問4個字節(jié)空間,子類還有_b,若轉(zhuǎn)為子類,此時指針就會越界,指針越界后就能訪問_b,但是對于父類來說_b不屬于自己,所以會有隱患。
?若是父類指針,該指針若指向子類,該指針會受到父類類型的束縛,該指針只能訪問到父類的一部分,不能訪問子類,但是可以轉(zhuǎn)回子類,這種轉(zhuǎn)換就可以用dynamic_cast
如果pa是指向子類,那么可以轉(zhuǎn)換,轉(zhuǎn)換表達(dá)式返回正確的地址。
如果pa是指向父類,那么不能轉(zhuǎn)換,轉(zhuǎn)換表達(dá)式返回nullptr。
pa此時是子類指針,轉(zhuǎn)換成功
?pa是父類指針,轉(zhuǎn)換失敗
?如果用C語言的強制類型轉(zhuǎn)換,這里都是轉(zhuǎn)換成功,但是遇到父類指針就會有風(fēng)險,會發(fā)生指針越界
延伸問題?
?這里第一組數(shù)據(jù)不一樣是因為發(fā)生了切片,但是后面?zhèn)z組數(shù)據(jù)ptr1=ptr2,ptr3=ptr4,這是為什么?
?這是因為類型轉(zhuǎn)換后不再發(fā)生切片,ptr1和ptr2都指向開頭這塊地址,ptr3和ptr4也同理
如果不是虛函數(shù)dynamic_cast就無法使用
‘
注意
強制類型轉(zhuǎn)換關(guān)閉或掛起了正常的類型檢查,每次使用強制類型轉(zhuǎn)換前,程序員應(yīng)該仔細(xì)考慮是
否還有其他不同的方法達(dá)到同一目的,如果非強制類型轉(zhuǎn)換不可,則應(yīng)限制強制轉(zhuǎn)換值的作用
域,以減少發(fā)生錯誤的機會。強烈建議:避免使用強制類型轉(zhuǎn)換
?
?RTTI(了解)
?RTTI:Run-time Type identification的簡稱,即:運行時類型識別。
C++通過以下方式來支持RTTI:
1. typeid運算符
2. dynamic_cast運算符
3. decltype
?