仔細(xì)想想地位卑賤的類(lèi)型轉(zhuǎn)換功能(cast),其在程序設(shè)計(jì)中的地位就象goto語(yǔ)句一樣令人鄙視。但是它還不是無(wú)法令人忍受,因?yàn)楫?dāng)在某些緊要的關(guān)頭,類(lèi)型轉(zhuǎn)換還是必需的,這時(shí)它是一個(gè)必需品。
如果用上述新的類(lèi)型轉(zhuǎn)換方法,你應(yīng)該這樣寫(xiě):
這樣的類(lèi)型轉(zhuǎn)換不論是對(duì)人工還是對(duì)程序都很容易識(shí)別。 static_cast 在功能上基本上與C風(fēng)格的類(lèi)型轉(zhuǎn)換一樣強(qiáng)大,含義也一樣。它也有功能上限制。例如,你不能用static_cast象用C風(fēng)格的類(lèi)型轉(zhuǎn)換一樣把struct轉(zhuǎn)換成int類(lèi)型或者把double類(lèi)型轉(zhuǎn)換成指針類(lèi)型,另外,static_cast不能從表達(dá)式中去除const屬性,因?yàn)榱硪粋€(gè)新的類(lèi)型轉(zhuǎn)換操作符const_cast有這樣的功能。 其它新的C++類(lèi)型轉(zhuǎn)換操作符被用在需要更多限制的地方。const_cast 用于類(lèi)型轉(zhuǎn)換掉表達(dá)式的const或volatileness屬性。通過(guò)使用const_cast,你向人們和編譯器強(qiáng)調(diào)你通過(guò)類(lèi)型轉(zhuǎn)換想做的只是改變一些東西的constness 或者 volatileness屬性。這個(gè)含義被編譯器所約束。如果你試圖使用const_cast來(lái)完成修改constness 或者 volatileness屬性之外的事情,你的類(lèi)型轉(zhuǎn)換將被拒絕。下面是一些例子:
到目前為止,const_cast最普通的用途就是轉(zhuǎn)換掉對(duì)象的const屬性。 第二種特殊的類(lèi)型轉(zhuǎn)換符是dynamic_cast,它被用于安全地沿著類(lèi)的繼承關(guān)系向下進(jìn)行類(lèi)型轉(zhuǎn)換。這就是說(shuō),你能用dynamic_cast把指向基類(lèi)的指針或引用轉(zhuǎn)換成指向其派生類(lèi)或其兄弟類(lèi)的指針或引用,而且你能知道轉(zhuǎn)換是否成功。失敗的轉(zhuǎn)換將返回空指針(當(dāng)對(duì)指針進(jìn)行類(lèi)型轉(zhuǎn)換時(shí))或者拋出異常(當(dāng)對(duì)引用進(jìn)行類(lèi)型轉(zhuǎn)換時(shí)):
dynamic_casts在幫助你瀏覽繼承層次上是有限制的。它不能被用于缺乏虛函數(shù)的類(lèi)型上,也不能用它來(lái)轉(zhuǎn)換掉constness:
如你想在沒(méi)有繼承關(guān)系的類(lèi)型中進(jìn)行轉(zhuǎn)換,你可能想到static_cast。如果是為了去除const,你總得用const_cast。 這四個(gè)類(lèi)型轉(zhuǎn)換符中的最后一個(gè)是reinterpret_cast。這個(gè)操作符被用于的類(lèi)型轉(zhuǎn)換的轉(zhuǎn)換結(jié)果幾乎都是實(shí)現(xiàn)時(shí)定義(implementation-defined)。因此,使用reinterpret_casts的代碼很難移植。 reinterpret_casts的最普通的用途就是在函數(shù)指針類(lèi)型之間進(jìn)行轉(zhuǎn)換。例如,假設(shè)你有一個(gè)函數(shù)指針數(shù)組:
讓我們假設(shè)你希望(因?yàn)槟承┠涿畹脑颍┌岩粋€(gè)指向下面函數(shù)的指針存入funcPtrArray數(shù)組:
你不能不經(jīng)過(guò)類(lèi)型轉(zhuǎn)換而直接去做,因?yàn)閐oSomething函數(shù)對(duì)于funcPtrArray數(shù)組來(lái)說(shuō)有一個(gè)錯(cuò)誤的類(lèi)型。在FuncPtrArray數(shù)組里的函數(shù)返回值是void類(lèi)型,而doSomething函數(shù)返回值是int類(lèi)型。
轉(zhuǎn)換函數(shù)指針的代碼是不可移植的(C++不保證所有的函數(shù)指針都被用一樣的方法表示),在一些情況下這樣的轉(zhuǎn)換會(huì)產(chǎn)生不正確的結(jié)果(參見(jiàn)條款31),所以你應(yīng)該避免轉(zhuǎn)換函數(shù)指針類(lèi)型,除非你處于著背水一戰(zhàn)和尖刀架喉的危急時(shí)刻。一把鋒利的刀。一把非常鋒利的刀。 如果你使用的編譯器缺乏對(duì)新的類(lèi)型轉(zhuǎn)換方式的支持,你可以用傳統(tǒng)的類(lèi)型轉(zhuǎn)換方法代替static_cast, const_cast, and reinterpret_cast。也可以用下面的宏替換來(lái)模擬新的類(lèi)型轉(zhuǎn)換語(yǔ)法:
你可以象這樣使用使用:
這些模擬不會(huì)象真實(shí)的操作符一樣安全,但是當(dāng)你的編譯器可以支持新的的類(lèi)型轉(zhuǎn)換時(shí)它們可以簡(jiǎn)化你把代碼升級(jí)的過(guò)程。 沒(méi)有一個(gè)容易的方法來(lái)模擬dynamic_cast的操作,但是很多函數(shù)庫(kù)提供了函數(shù),安全地在派生類(lèi)與基類(lèi)之間的進(jìn)行類(lèi)型轉(zhuǎn)換。如果你沒(méi)有這些函數(shù)而你有必須進(jìn)行這樣的類(lèi)型轉(zhuǎn)換,你也可以回到C風(fēng)格的類(lèi)型轉(zhuǎn)換方法上,但是這樣的話(huà)你將不能獲知類(lèi)型轉(zhuǎn)換是否失敗。當(dāng)然,你也可以定義一個(gè)宏來(lái)模擬dynamic_cast的功能,就象模擬其它的類(lèi)型轉(zhuǎn)換一樣:
請(qǐng)記住,這個(gè)模擬并不能完全實(shí)現(xiàn)dynamic_cast的功能,它沒(méi)有辦法知道轉(zhuǎn)換是否失敗。 我知道,是的,我知道,新的類(lèi)型轉(zhuǎn)換操作符不是很美觀而且用鍵盤(pán)鍵入也很麻煩。如果你發(fā)現(xiàn)它們看上去實(shí)在令人討厭,C風(fēng)格的類(lèi)型轉(zhuǎn)換還可以繼續(xù)使用并且合法。然而正是因?yàn)樾碌念?lèi)型轉(zhuǎn)換符缺乏美感才能使它彌補(bǔ)了在含義精確性和可辨認(rèn)性上的缺點(diǎn),并且使用新類(lèi)型轉(zhuǎn)換符的程序更容易被解析(不論是對(duì)人工還是對(duì)于工具程序),它們?cè)试S編譯器檢測(cè)出原來(lái)不能發(fā)現(xiàn)的錯(cuò)誤。這些都是放棄C風(fēng)格類(lèi)型轉(zhuǎn)換方法的強(qiáng)有力的理由,還有第三個(gè)理由:也許讓類(lèi)型轉(zhuǎn)換符不美觀和鍵入麻煩是一件好事。 |
|
來(lái)自: lchjczw > 《C 基礎(chǔ)學(xué)習(xí)》