欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

C++的另一種錯誤處理策略是什么

C++的另一種錯誤處理策略是什么,針對這個問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

專注于為中小企業(yè)提供成都做網(wǎng)站、成都網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)渝中免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了數(shù)千家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

這篇短文是討論一個大多數(shù)程序員都感興趣的一個話題:錯誤處理。錯誤處理是編程的一個“黑暗面”。它既是應(yīng)用程序的“現(xiàn)實世界”的關(guān)鍵點(diǎn),也是一個你想隱藏的復(fù)雜業(yè)務(wù)。

在早期的C編程生涯中,我知道三種錯誤處理的方式。

C語言的方式:返回錯誤碼

C語言風(fēng)格的錯誤處理是最簡單的,但是并不***。

C語言風(fēng)格的錯誤處理依賴于“當(dāng)程序遇到錯誤時返回一個錯誤碼”。這里是一個簡單的例子:

int find_slash(const char *str) {     int i = 0;        while (str[i] && str[i] != '/')           i++;        if (str[i] == '\0')         return -1; //Error code        //True value     return i; }    // . . .    if (find_slash(string) == -1) {         //error handling }

使用這種方式的有什么好處?

你可以在調(diào)用函數(shù)之后直接處理錯誤碼(在C語言中,你也會這樣處理),顯示一個錯誤消息或者直接終止程序。或者僅僅恢復(fù)程序最近的一個狀態(tài),終止計算。

當(dāng)你找不到錯誤處理在哪里的時候,你只需要后頭看看函數(shù)調(diào)用,錯誤處理就在那個附近。

使用這種方式有什么不好?

有人可能會告訴你,這種異常/錯誤處理方式和“執(zhí)行邏輯”混在了一起。當(dāng)你順序地閱讀這些代碼的時候就行程序執(zhí)行一樣,你看到了一會錯誤處理,一會程序執(zhí)行。這樣很糟糕,你可能更喜歡只讀程序執(zhí)行邏輯或者錯誤處理邏輯。

并且你被限定使用錯誤碼,如果你想要提供更多的信息,你需要創(chuàng)建一些功能函數(shù)比如:errstr或者提供全局變量。

使用C++的方式

C++作為對C的增強(qiáng),引入了一種新的錯誤處理方式——異常。異常通過拋出一個錯誤的方式來中斷正常代碼執(zhí)行邏輯,并可以被其他地方所捕獲。下面是一個簡單的例子:

int find_slash(const char *str) {     int i = 0;        while (str[i] && str[i] != '/')           i++;        if (str[i] == '\0')         throw AnException("Error message");        //True value     return i; }    // . . .    try {     find_slash(string); } catch(AnException& e) {    //Handle exception }

這樣做的好處?

程序邏輯和錯誤處理分離了。一邊你可以看到函數(shù)是如何工作的,而另一邊你可以看到函數(shù)失敗時候是怎么處理的。這樣做很***,可以很容易看出錯誤處理和正常程序邏輯。

另外,現(xiàn)在你可以為你的錯誤提供你需要的盡可能多的信息,因為你可以將需要的內(nèi)容填充在自定義異常對象里。

這樣做的壞處

編寫詳盡的異常處理變得很冗。你需要一個異常樹,但是***不要太大,這樣,你可以選擇捕獲感興趣的異常。同時,內(nèi)部需要提供錯誤碼,來獲知究竟發(fā)生了什么,同時需要檢索一些錯誤消息,等等。編寫寫異常類通常都是冗長,這是將信息嵌入到錯誤里來靈活處理更多的信息的成本。

這里的錯誤處理哲學(xué)是將錯誤盡可能推遲到需要處理的地方再處理,當(dāng)你不知道程序執(zhí)行過程究竟哪里會產(chǎn)生一個錯誤,你需要跳過不同的文件和功能函數(shù)來 查找,這通常都是困難的,如果你在一個很深的調(diào)用樹(這里意思是當(dāng)你將函數(shù)調(diào)用繪制出一個圖形,其形狀類似一棵樹)上引發(fā)了一個異常,你需要指定在哪里來 處理這個異常,當(dāng)它被處理的時候,它又是在哪里發(fā)生的。特別是當(dāng)你的程序很大,又是很早之前編寫,有恰巧設(shè)計不夠良好的時候,就更加顯得困難。而大多數(shù)商 業(yè)項目都是這樣。

所以我覺得“異常是危險的”。雖然它提供了一種良好的方式來處理錯誤——僅限于一些小項目,并且這里的調(diào)用圖簡單且易于掌握時候。

錯誤封裝的模式

我這里把它叫做一種模式,所以人們不必害怕?lián)摹:竺妫視o它一種更好的命名,所以請不要著急。

錯誤封裝的主旨是創(chuàng)建一種封裝來包含錯誤消息或者錯誤的返回值。我們通常會選擇字符串而不是其他,因為這也并不容易實現(xiàn)。我們盡力保證語法的可讀性,可理解,并且容易應(yīng)用。我們不處理拷貝構(gòu)造或者多參數(shù)函數(shù)及返回值,這里僅給出一個盡可能簡單的例子。

讓我們以下面的例子開始:

E<int> find_slash(const char* str) {     int i = 0;        while (str[i] && str[i] != '/')           i++;        if (str[i] == '\0')         return fail<int>("Error message");        //True value     return ret(i); }    // . . .    auto v = find_slash(string); if(!v) {     //Handle exception }

乍一看,這里有點(diǎn)類似C語言的風(fēng)格,但是不是,為表明這一點(diǎn),請看接下來的多個函數(shù)調(diào)用例子:

E<int> find_slash(const char*); E<int> do_some_arithmetic(int); E<std::string> format(int); E<void> display(std::string);    auto v = ret(string)          .bind(find_slash)          .bind(do_some_arithmetic)          .bind(format)          .bind(display);    if(!v) {     //Handle error }

好了,這里發(fā)生了什么?bind是一個成員函數(shù)來綁定你的函數(shù)調(diào)用,試著去應(yīng)用它。如果錯誤裝箱里面含有一個值,那么它就應(yīng)用于函數(shù)調(diào)用,繼續(xù)返回一個錯誤裝箱(編譯器不允許你返回一個不帶錯誤裝箱的函數(shù))。

所以,我們鏈?zhǔn)秸{(diào)用了find_slashe,do_some_arithmetic, format和display.它們都不處理錯誤裝箱,由于bind函數(shù)的作用,我們將函數(shù)E<something_out> f(something_in)返回結(jié)果給E<something_out> f(E<something_in>)函數(shù)做參數(shù)。

這里的好處是什么?

再一次,函數(shù)邏輯(調(diào)用鏈)和錯誤處理分離了。和異常一樣,我們可以簡單讀一下函數(shù)調(diào)用鏈來了解代碼邏輯,而不用關(guān)心執(zhí)行是在哪里被中斷的。事實上,函數(shù)調(diào)用鏈可以在任何調(diào)用時被中斷。但是我們可以認(rèn)為沒有錯誤發(fā)生,如果我們的邏輯是正確的,可以很快速檢查。

當(dāng)然,類型推導(dǎo)會阻止你在調(diào)用display之后繼續(xù)進(jìn)行綁定。所以我們也沒有失去類型能力。

注意,我們沒有在其他地方調(diào)用這些函數(shù),我們在***將這些方法組裝在一起。這里是關(guān)鍵,你應(yīng)該編寫一些小的模塊函數(shù)(另外,注意:你應(yīng)該編寫模板函 數(shù)使其工作)接收一個值,然后計算一個新值或者返回失敗。在每一步中,你都不需要考慮可能出現(xiàn)錯誤導(dǎo)致你的控制流中斷,并且校驗?zāi)闶欠裨谝粋€有效的狀態(tài)上 (異常安全基于查詢每個函數(shù)調(diào)用,指出函數(shù)是否中斷你的控制流程,如果出現(xiàn)異常會發(fā)生什么),基于這一點(diǎn),這樣做更安全。

和異常一樣,我們可以處理很詳細(xì)的信息,盡管這里我們編寫的是一個偏模板函數(shù),所以也容易理解一些。

我們可以很容易放置異常處理邏輯,把它放在函數(shù)調(diào)用鏈之后(除非這個返回值還需要進(jìn)一步被鏈接)。現(xiàn)在,我們有一個大的的執(zhí)行流,沒有中斷,使用小 的函數(shù)處理流程,容易定位。當(dāng)需要添加一個新的錯誤時,你只需找到那些函數(shù),通過函數(shù)調(diào)用鏈,你可以直接定位到處理位置,并根據(jù)需要添加。大型項目變得更 加的線性化,并且更易讀。

這樣做有什么不足?

首先,這是一個新的處理方式,并且和C++的方式不兼容。這不是一個標(biāo)準(zhǔn)處理方法,當(dāng)你使用stl時,你仍然需要使用異常。

對于我來說,這樣做還是有點(diǎn)冗長。需要顯式編寫fail<int>(&hellip;)的模板推導(dǎo)顯得有點(diǎn)怪異,如果你有個多態(tài)錯誤類型就更糟了,你不得不這樣寫fail<return_type, error_type>("...").

當(dāng)函數(shù)有多個參數(shù)時編寫也很困難,在其他一些語言中,可以使用適用類型和抽象類型很好地解決這個問題,不過這在C++中不會提供。我想更適合使用bind2(E<a>, E<b>, f)bind3(E<a>, E<b>, E<c>, f),可變模板參數(shù)功能更有用。

為獲取封裝錯誤中的值,我們需要檢查這個值是否是有效值,接著調(diào)用一個“to_value”方法。我們沒辦法不通過檢查來做到這一點(diǎn)。我們希望的是“解構(gòu)”一個對象,不過這在C++中不支持,這也不是一些可以說“我們把它加入到下一個標(biāo)準(zhǔn)”的特性。

目前為止,我不知道讀者是否有方法將其適配到成員函數(shù)中,如果你有想法,請測試一下,如果可以,請告知我們。

實現(xiàn)原子錯誤處理

我實現(xiàn)了它,我定義了這個黑魔法的名字&mdash;&mdash;“原子化”,你可以認(rèn)為“原子化”是一個對值和錯誤上下文的裝箱,比如,一個box包含一個值或者什么也不包含是一個原子組(這里作為一個練習(xí),你可以試著實現(xiàn)一下)。

有點(diǎn)奇怪的是,從某個角度來說隊列是一個原子組,他們擁有一個上下文的值。

讓我們從上面的E模版類實現(xiàn)開始,這里使用了C++11標(biāo)準(zhǔn)中的decltype和auto -> decltype類型,允許自動推導(dǎo)得到表達(dá)式的類型,這非常有用。

這里的bind函數(shù)有點(diǎn)怪異,但是他實現(xiàn)了我剛才提到的內(nèi)容。

關(guān)于C++的另一種錯誤處理策略是什么問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識。

文章標(biāo)題:C++的另一種錯誤處理策略是什么
鏈接分享:http://chinadenli.net/article36/jijipg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計公司網(wǎng)站營銷手機(jī)網(wǎng)站建設(shè)面包屑導(dǎo)航微信小程序網(wǎng)站排名

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)