国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

明確C++風(fēng)格的類型轉(zhuǎn)換的用法

2019-11-17 05:23:31
字體:
供稿:網(wǎng)友

  仔細(xì)想想地位卑賤的類型轉(zhuǎn)換功能(cast),其在程序設(shè)計(jì)中的地位就象goto語句一樣令人鄙視。但是它還不是無法令人忍受,因?yàn)楫?dāng)在某些緊要的關(guān)頭,類型轉(zhuǎn)換還是必需的,這時(shí)它是一個(gè)必需品。

  不過C風(fēng)格的類型轉(zhuǎn)換并不代表所有的類型轉(zhuǎn)換功能。

  一來它們過于粗魯,能答應(yīng)你在任何類型之間進(jìn)行轉(zhuǎn)換。不過假如要進(jìn)行更精確的類型轉(zhuǎn)換,這會(huì)是一個(gè)優(yōu)點(diǎn)。在這些類型轉(zhuǎn)換中存在著巨大的不同,例如把一個(gè)指向const對象的指針(pointer-to-const-object)轉(zhuǎn)換成指向非const對象的指針(pointer-to-non-const-object)(即一個(gè)僅僅去除const的類型轉(zhuǎn)換),把一個(gè)指向基類的指針轉(zhuǎn)換成指向子類的指針(即完全改變對象類型)。傳統(tǒng)的C風(fēng)格的類型轉(zhuǎn)換不對上述兩種轉(zhuǎn)換進(jìn)行區(qū)分。(這一點(diǎn)也不令人驚奇,因?yàn)镃風(fēng)格的類型轉(zhuǎn)換是為C語言設(shè)計(jì)的,而不是為C++語言設(shè)計(jì)的)。

  二來C風(fēng)格的類型轉(zhuǎn)換在程序語句中難以識(shí)別。在語法上,類型轉(zhuǎn)換由圓括號(hào)和標(biāo)識(shí)符組成,而這些可以用在C++中的任何地方。這使得回答象這樣一個(gè)最基本的有關(guān)類型轉(zhuǎn)換的問題變得很困難:“在這個(gè)程序中是否使用了類型轉(zhuǎn)換?”。這是因?yàn)槿斯ら喿x很可能忽略了類型轉(zhuǎn)換的語句,而利用象grep的工具程序也不能從語句構(gòu)成上區(qū)分出它們來。

  C++通過引進(jìn)四個(gè)新的類型轉(zhuǎn)換操作符克服了C風(fēng)格類型轉(zhuǎn)換的缺點(diǎn),這四個(gè)操作符是, static_cast, const_cast, dynamic_cast, 和reinterPRet_cast。在大多數(shù)情況下,對于這些操作符你只需要知道原來你習(xí)慣于這樣寫,

(type) eXPression
  而現(xiàn)在你總應(yīng)該這樣寫:

static_cast<type>(expression)
  例如,假設(shè)你想把一個(gè)int轉(zhuǎn)換成double,以便讓包含int類型變量的表達(dá)式產(chǎn)生出浮點(diǎn)數(shù)值的結(jié)果。假如用C風(fēng)格的類型轉(zhuǎn)換,你能這樣寫:

int firstNumber, secondNumber;
...
double result = ((double)firstNumber)/secondNumber;
  假如用上述新的類型轉(zhuǎn)換方法,你應(yīng)該這樣寫:

double result = static_cast<double>(firstNumber)/secondNumber;
  這樣的類型轉(zhuǎn)換不論是對人工還是對程序都很輕易識(shí)別。

   static_cast在功能上基本上與C風(fēng)格的類型轉(zhuǎn)換一樣強(qiáng)大,含義也一樣。它也有功能上限制。例如,你不能用static_cast象用C風(fēng)格的類型轉(zhuǎn)換一樣把strUCt轉(zhuǎn)換成int類型或者把double類型轉(zhuǎn)換成指針類型,另外,static_cast不能從表達(dá)式中去除const屬性,因?yàn)榱硪粋€(gè)新的類型轉(zhuǎn)換操作符const_cast有這樣的功能。
其它新的C++類型轉(zhuǎn)換操作符被用在需要更多限制的地方。const_cast用于類型轉(zhuǎn)換掉表達(dá)式的const或volatileness屬性。通過使用const_cast,你向人們和編譯器強(qiáng)調(diào)你通過類型轉(zhuǎn)換想做的只是改變一些東西的constness或者volatileness屬性。這個(gè)含義被編譯器所約束。假如你試圖使用const_cast來完成修改constness 或者volatileness屬性之外的事情,你的類型轉(zhuǎn)換將被拒絕。下面是一些例子:

class Widget { ... };
class SpecialWidget: public Widget { ... };
void update(SpecialWidget *psw);
SpecialWidget sw; // sw 是一個(gè)非const 對象。
const SpecialWidget& csw = sw; // csw 是sw的一個(gè)引用
// 它是一個(gè)const 對象
update(&csw); // 錯(cuò)誤!不能傳遞一個(gè)const SpecialWidget* 變量
// 給一個(gè)處理SpecialWidget*類型變量的函數(shù)
update(const_cast<SpecialWidget*>(&csw));
// 正確,csw的const被顯示地轉(zhuǎn)換掉(
// csw和sw兩個(gè)變量值在update
//函數(shù)中能被更新)
update((SpecialWidget*)&csw);
// 同上,但用了一個(gè)更難識(shí)別
//的C風(fēng)格的類型轉(zhuǎn)換
Widget *pw = new SpecialWidget;
update(pw); // 錯(cuò)誤!pw的類型是Widget*,但是
// update函數(shù)處理的是SpecialWidget*類型
update(const_cast<SpecialWidget*>(pw));
// 錯(cuò)誤!const_cast僅能被用在影響
// constness or volatileness的地方上。,
// 不能用在向繼續(xù)子類進(jìn)行類型轉(zhuǎn)換。
  到目前為止,const_cast最普通的用途就是轉(zhuǎn)換掉對象的const屬性。

  第二種非凡的類型轉(zhuǎn)換符是dynamic_cast,它被用于安全地沿著類的繼續(xù)關(guān)系向下進(jìn)行類型轉(zhuǎn)換。這就是說,你能用dynamic_cast把指向基類的指針或引用轉(zhuǎn)換成指向其派生類或其兄弟類的指針或引用,而且你能知道轉(zhuǎn)換是否成功。失敗的轉(zhuǎn)換將返回空指針(當(dāng)對指針進(jìn)行類型轉(zhuǎn)換時(shí))或者拋出異常(當(dāng)對引用進(jìn)行類型轉(zhuǎn)換時(shí)):


Widget *pw;
...
update(dynamic_cast<SpecialWidget*>(pw));
// 正確,傳遞給update函數(shù)一個(gè)指針
// 是指向變量類型為SpecialWidget的pw的指針
// 假如pw確實(shí)指向一個(gè)對象,
// 否則傳遞過去的將使空指針。
void updateViaRef(SpecialWidget& rsw);
updateViaRef(dynamic_cast<SpecialWidget&>(*pw));
//正確。傳遞給updateViaRef函數(shù)
// SpecialWidget pw 指針,假如pw
// 確實(shí)指向了某個(gè)對象
// 否則將拋出異常
dynamic_casts在幫助你瀏覽繼續(xù)層次上是有限制的。它不能被用于缺乏虛函數(shù)的類型上(參見條款M24),也不能用它來轉(zhuǎn)換掉constness:
int firstNumber, secondNumber;
...
double result = dynamic_cast<double>(firstNumber)/secondNumber;
// 錯(cuò)誤!沒有繼續(xù)關(guān)系
const SpecialWidget sw;
...
update(dynamic_cast<SpecialWidget*>(&sw));
// 錯(cuò)誤! dynamic_cast不能轉(zhuǎn)換
// 掉const。
  如你想在沒有繼續(xù)關(guān)系的類型中進(jìn)行轉(zhuǎn)換,你可能想到static_cast。假如是為了去除const,你總得用const_cast。

  這四個(gè)類型轉(zhuǎn)換符中的最后一個(gè)是reinterpret_cast。使用這個(gè)操作符的類型轉(zhuǎn)換,其的轉(zhuǎn)換結(jié)果幾乎都是執(zhí)行期定義(implementation-defined)。因此,使用reinterpret_casts的代碼很難移植。

  reinterpret_casts的最普通的用途就是在函數(shù)指針類型之間進(jìn)行轉(zhuǎn)換。例如,假設(shè)你有一個(gè)函數(shù)指針數(shù)組:

typedef void (*FuncPtr)(); // FuncPtr is 一個(gè)指向函數(shù)
// 的指針,該函數(shù)沒有參數(shù)
// 返回值類型為void
FuncPtr funcPtrArray[10]; // funcPtrArray 是一個(gè)能容納
// 10個(gè)FuncPtrs指針的數(shù)組
  讓我們假設(shè)你希望(因?yàn)槟承┠涿畹脑颍┌岩粋€(gè)指向下面函數(shù)的指針存入funcPtrArray數(shù)組:

int doSomething();
  你不能不經(jīng)過類型轉(zhuǎn)換而直接去做,因?yàn)閐oSomething函數(shù)對于funcPtrArray數(shù)組來說有一個(gè)錯(cuò)誤的類型。在FuncPtrArray數(shù)組里的函數(shù)返回值是void類型,而doSomething函數(shù)返回值是int類型。

funcPtrArray[0] = &doSomething; // 錯(cuò)誤!類型不匹配
reinterpret_cast可以讓你迫使編譯器以你的方法去看待它們:
funcPtrArray[0] = // this compiles
reinterpret_cast<FuncPtr>(&doSomething);
  轉(zhuǎn)換函數(shù)指針的代碼是不可移植的(C++不保證所有的函數(shù)指針都被用一樣的方法表示),在一些情況下這樣的轉(zhuǎn)換會(huì)產(chǎn)生不正確的結(jié)果(參見條款M31),所以你應(yīng)該避免轉(zhuǎn)換函數(shù)指針類型,除非你處于著背水一戰(zhàn)和尖刀架喉的危急時(shí)刻。一把鋒利的刀。一把非常鋒利的刀。

  假如你使用的編譯器缺乏對新的類型轉(zhuǎn)換方式的支持,你可以用傳統(tǒng)的類型轉(zhuǎn)換方法代替static_cast, const_cast, 以及reinterpret_cast。也可以用下面的宏替換來模擬新的類型轉(zhuǎn)換語法:

#define static_cast(TYPE,EXPR) ((TYPE)(EXPR))
#define const_cast(TYPE,EXPR) ((TYPE)(EXPR))
#define reinterpret_cast(TYPE,EXPR) ((TYPE)(EXPR))
  你可以象這樣使用使用:

double result = static_cast(double, firstNumber)/secondNumber;
update(const_cast(SpecialWidget*, &sw));
funcPtrArray[0] = reinterpret_cast(FuncPtr, &doSomething);
  這些模擬不會(huì)象真實(shí)的操作符一樣安全,但是當(dāng)你的編譯器可以支持新的的類型轉(zhuǎn)換時(shí),它們可以簡化你把代碼升級(jí)的過程。

  沒有一個(gè)輕易的方法來模擬dynamic_cast的操作,但是很多函數(shù)庫提供了函數(shù),安全地在派生類與基類之間進(jìn)行類型轉(zhuǎn)換。假如你沒有這些函數(shù)而你有必須進(jìn)行這樣的類型轉(zhuǎn)換,你也可以回到C風(fēng)格的類型轉(zhuǎn)換方法上,但是這樣的話你將不能獲知類型轉(zhuǎn)換是否失敗。當(dāng)然,你也可以定義一個(gè)宏來模擬dynamic_cast的功能,就象模擬其它的類型轉(zhuǎn)換一樣:

#define dynamic_cast(TYPE,EXPR) (TYPE)(EXPR)
  請記住,這個(gè)模擬并不能完全實(shí)現(xiàn)dynamic_cast的功能,它沒有辦法知道轉(zhuǎn)換是否失敗。

  我知道,是的,我知道,新的類型轉(zhuǎn)換操作符不是很美觀而且用鍵盤鍵入也很麻煩。假如你發(fā)現(xiàn)它們看上去實(shí)在令人討厭,C風(fēng)格的類型轉(zhuǎn)換還可以繼續(xù)使用并且合法。然而,正是因?yàn)樾碌念愋娃D(zhuǎn)換符缺乏美感才能使它彌補(bǔ)了在含義精確性和可辨認(rèn)性上的缺點(diǎn)。并且,使用新類型轉(zhuǎn)換符的程序更輕易被解析(不論是對人工還是對于工具程序),它們答應(yīng)編譯器檢測出原來不能發(fā)現(xiàn)的錯(cuò)誤。這些都是放棄C風(fēng)格類型轉(zhuǎn)換方法的強(qiáng)有力的理由。還有第三個(gè)理由:也許讓類型轉(zhuǎn)換符不美觀和鍵入麻煩是一件好事。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 石景山区| 临高县| 乌什县| 贵南县| 丹凤县| 红原县| 醴陵市| 闵行区| 萨迦县| 东阿县| 舞阳县| 雷州市| 徐闻县| 莒南县| 博兴县| 新巴尔虎左旗| 葫芦岛市| 麻江县| 弥渡县| SHOW| 汨罗市| 嘉兴市| 桐乡市| 仪陇县| 同德县| 裕民县| 鄂尔多斯市| 铜山县| 炎陵县| 台前县| 略阳县| 林芝县| 信阳市| 新巴尔虎右旗| 易门县| 荃湾区| 汝州市| 西乌| 定襄县| 宿州市| 安丘市|