欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++?異常處理機(jī)制與自定義異常體系處理方式

 更新時(shí)間:2024年12月10日 10:06:10   作者:藤椒味的火腿腸真不錯(cuò)  
本節(jié)將詳細(xì)介紹C++異常處理的相關(guān)概念、用法以及如何通過(guò)自定義異常體系來(lái)滿足程序的需求,同時(shí),我們將對(duì)比C語(yǔ)言的傳統(tǒng)錯(cuò)誤處理方式,分析C++異常機(jī)制的優(yōu)缺點(diǎn),并探討標(biāo)準(zhǔn)庫(kù)中提供的異常體系,幫助開發(fā)者更好地理解和使用C++的異常處理功能,感興趣的朋友一起看看吧

 前言??????

在程序開發(fā)中,錯(cuò)誤和異常的處理是至關(guān)重要的,它直接影響到程序的健壯性和穩(wěn)定性。C語(yǔ)言的錯(cuò)誤處理主要依賴返回值和錯(cuò)誤碼,雖然這種方式簡(jiǎn)單直接,但在復(fù)雜的程序中,錯(cuò)誤處理代碼往往難以維護(hù)且容易出錯(cuò)。相比之下,C++引入的異常處理機(jī)制提供了一種更為高效和靈活的錯(cuò)誤處理方式,使得程序的錯(cuò)誤管理更加清晰和優(yōu)雅。

本節(jié)將詳細(xì)介紹C++異常處理的相關(guān)概念、用法以及如何通過(guò)自定義異常體系來(lái)滿足程序的需求。同時(shí),我們將對(duì)比C語(yǔ)言的傳統(tǒng)錯(cuò)誤處理方式,分析C++異常機(jī)制的優(yōu)缺點(diǎn),并探討標(biāo)準(zhǔn)庫(kù)中提供的異常體系,幫助開發(fā)者更好地理解和使用C++的異常處理功能。

1.C語(yǔ)言傳統(tǒng)的處理錯(cuò)誤的方式 ??

C語(yǔ)言傳統(tǒng)的錯(cuò)誤處理機(jī)制主要有兩種方式:終止程序返回錯(cuò)誤碼。這兩種方式雖然簡(jiǎn)單易用,但各自也有其局限性和缺陷,尤其是在處理復(fù)雜錯(cuò)誤或大規(guī)模程序時(shí),往往會(huì)導(dǎo)致維護(hù)上的困難。 

1. 終止程序

一種常見(jiàn)的錯(cuò)誤處理方式是直接終止程序,這種方式通常是通過(guò)使用assert宏實(shí)現(xiàn)的。assert會(huì)在程序運(yùn)行時(shí)對(duì)條件進(jìn)行檢查,如果條件不滿足,則程序會(huì)立即終止并輸出錯(cuò)誤信息。

代碼如下:

#include <assert.h>
void foo(int x) {
    assert(x != 0);  // 如果x為0,程序終止
    printf("x is not zero\n");
}
int main() {
    foo(0);  // 觸發(fā)斷言,程序終止
    return 0;
}

缺陷

  • 用戶難以接受:程序直接終止,尤其是當(dāng)發(fā)生一些小錯(cuò)誤或邊界條件時(shí),用戶體驗(yàn)很差。
  • 適用場(chǎng)景有限:這種方式適用于嚴(yán)重錯(cuò)誤(如內(nèi)存錯(cuò)誤、除0錯(cuò)誤等),但不適合所有情況,因?yàn)榇蠖鄶?shù)程序錯(cuò)誤并不需要完全終止程序。

當(dāng)程序遇到無(wú)法恢復(fù)的錯(cuò)誤時(shí),assert可以有效地幫助開發(fā)者檢測(cè)出問(wèn)題。但是,當(dāng)程序出現(xiàn)一些非致命錯(cuò)誤時(shí),用戶希望程序能夠優(yōu)雅地處理,而不是直接崩潰。 

2. 返回錯(cuò)誤碼

另一個(gè)常見(jiàn)的錯(cuò)誤處理方式是通過(guò)返回錯(cuò)誤碼來(lái)通知程序出現(xiàn)了問(wèn)題。這種方法在C語(yǔ)言中非常普遍,許多標(biāo)準(zhǔn)庫(kù)函數(shù)(如malloc、fopen)都通過(guò)返回一個(gè)特殊的錯(cuò)誤碼來(lái)表示函數(shù)執(zhí)行失敗。開發(fā)者需要根據(jù)返回值來(lái)判斷錯(cuò)誤,并做相應(yīng)的處理。

比如,malloc在分配內(nèi)存失敗時(shí)返回NULL,fopen在打開文件失敗時(shí)返回NULL,errno則是一個(gè)全局變量,用于記錄最近一次系統(tǒng)調(diào)用的錯(cuò)誤碼。

缺陷

  • 需要手動(dòng)檢查錯(cuò)誤碼:程序員必須檢查每個(gè)函數(shù)調(diào)用的返回值,以便發(fā)現(xiàn)錯(cuò)誤。這導(dǎo)致了大量重復(fù)的錯(cuò)誤處理代碼,增加了維護(hù)成本。
  • 錯(cuò)誤信息不夠直觀:雖然可以通過(guò)errno來(lái)獲取詳細(xì)的錯(cuò)誤信息,但這通常不如異常機(jī)制直觀。錯(cuò)誤碼本身通常是數(shù)字,缺乏對(duì)錯(cuò)誤本質(zhì)的描述,需要額外的邏輯去理解錯(cuò)誤碼的含義。
  • 錯(cuò)誤處理分散:程序中多處調(diào)用的函數(shù)可能會(huì)返回不同的錯(cuò)誤碼,處理這些錯(cuò)誤的邏輯往往分散在代碼的各個(gè)地方,導(dǎo)致代碼的可讀性差。

3.實(shí)際使用中的情況

在實(shí)際的C語(yǔ)言開發(fā)中,返回錯(cuò)誤碼是最常見(jiàn)的錯(cuò)誤處理方式。C語(yǔ)言沒(méi)有內(nèi)建的異常機(jī)制,所以程序員必須通過(guò)檢查每個(gè)函數(shù)調(diào)用的返回值來(lái)手動(dòng)處理錯(cuò)誤。對(duì)于一些簡(jiǎn)單的錯(cuò)誤,返回錯(cuò)誤碼通常足夠。但對(duì)于較復(fù)雜的應(yīng)用程序,錯(cuò)誤碼的使用可能變得冗長(zhǎng)且難以維護(hù)。

在一些非常嚴(yán)重的錯(cuò)誤情況下(如內(nèi)存分配失敗、文件操作失敗等),開發(fā)者有時(shí)會(huì)選擇直接終止程序。例如,在發(fā)現(xiàn)內(nèi)存分配失敗時(shí),程序可能無(wú)法繼續(xù)執(zhí)行,這時(shí)直接通過(guò)exit()或其他方式終止程序可以避免進(jìn)一步的錯(cuò)誤。

2. C++異常概念??

C++的異常機(jī)制是一種專門用于處理錯(cuò)誤特殊情況的機(jī)制,可以在程序運(yùn)行時(shí)中斷當(dāng)前的控制流,并跳轉(zhuǎn)到一個(gè)可以處理該錯(cuò)誤的代碼塊。這種機(jī)制使得程序能夠優(yōu)雅地應(yīng)對(duì)各種錯(cuò)誤,而不是像C語(yǔ)言那樣依賴返回錯(cuò)誤碼或直接終止程序。 

2.1 C++異常的基本概念

異常 (Exception)

  • 異常是指程序在運(yùn)行時(shí)遇到的一種錯(cuò)誤或意外情況,這種情況可能會(huì)導(dǎo)致程序無(wú)法正常繼續(xù)執(zhí)行。
  • 異常通過(guò)throw關(guān)鍵字拋出,表示錯(cuò)誤已經(jīng)發(fā)生。
  • 異常可以是任意的C++對(duì)象(如數(shù)字、字符串、自定義類對(duì)象),但通常建議使用標(biāo)準(zhǔn)庫(kù)中的異常類(如std::exception及其派生類)。

異常處理機(jī)制 C++通過(guò)三種關(guān)鍵字實(shí)現(xiàn)異常處理:

  • try:定義一個(gè)代碼塊,用于包含可能發(fā)生異常的代碼。
  • throw:在異常發(fā)生時(shí),用于拋出異常。
  • catch:捕獲異常,并定義如何處理它。

2.2異常的拋出和匹配原則

1. 異常是通過(guò)拋出對(duì)象而引發(fā)的,該對(duì)象的類型決定了應(yīng)該激活哪個(gè)catch的處理代碼。

2. 被選中的處理代碼是調(diào)用鏈中與該對(duì)象類型匹配且離拋出異常位置最近的那一個(gè)。

3. 拋出異常對(duì)象后,會(huì)生成一個(gè)異常對(duì)象的拷貝,因?yàn)閽伋龅漠惓?duì)象可能是一個(gè)臨時(shí)對(duì)象,

所以會(huì)生成一個(gè)拷貝對(duì)象,這個(gè)拷貝的臨時(shí)對(duì)象會(huì)在被catch以后銷毀。(這里的處理類似

于函數(shù)的傳值返回)

4. catch(...)可以捕獲任意類型的異常,問(wèn)題是不知道異常錯(cuò)誤是什么。

5. 實(shí)際中拋出和捕獲的匹配原則有個(gè)例外,并不都是類型完全匹配,可以拋出的派生類對(duì)象,

使用基類捕獲,這個(gè)在實(shí)際中非常實(shí)用,我們后面會(huì)詳細(xì)講解這個(gè)。

在函數(shù)調(diào)用鏈中異常棧展開匹配原則

1. 首先檢查throw本身是否在try塊內(nèi)部,如果是再查找匹配的catch語(yǔ)句。如果有匹配的,則

調(diào)到catch的地方進(jìn)行處理。

2. 沒(méi)有匹配的catch則退出當(dāng)前函數(shù)棧,繼續(xù)在調(diào)用函數(shù)的棧中進(jìn)行查找匹配的catch。

3. 如果到達(dá)main函數(shù)的棧,依舊沒(méi)有匹配的,則終止程序。上述這個(gè)沿著調(diào)用鏈查找匹配的

catch子句的過(guò)程稱為棧展開。所以實(shí)際中我們最后都要加一個(gè)catch(...)捕獲任意類型的異

常,否則當(dāng)有異常沒(méi)捕獲,程序就會(huì)直接終止。

4. 找到匹配的catch子句并處理以后,會(huì)繼續(xù)沿著catch子句后面繼續(xù)執(zhí)行。

代碼案例:

double Division(int a, int b)
{
// 當(dāng)b == 0時(shí)拋出異常
if (b == 0)
throw "Division by zero condition!";
else
return ((double)a / (double)b);
}
void Func()
{
int len, time;
cin >> len >> time;
cout << Division(len, time) << endl;
}
int main()
{
try {
Func();
}
catch (const char* errmsg) {
cout << errmsg << endl;
}
catch(...){
cout<<"unkown exception"<<endl;
}
return 0;
}

這段代碼展示了如何在 C++ 中使用異常處理機(jī)制來(lái)管理錯(cuò)誤(特別是除以零的錯(cuò)誤)。通過(guò)使用 throwcatch,程序可以優(yōu)雅地處理異常,避免崩潰并提供友好的錯(cuò)誤信息。雖然當(dāng)前的異常處理簡(jiǎn)單直觀,但可以進(jìn)一步改進(jìn),采用標(biāo)準(zhǔn)異常類和更多輸入驗(yàn)證,以增強(qiáng)代碼的健壯性和可維護(hù)性。

2.3 異常的重新拋出

C++ 異常處理機(jī)制中的 異常重新拋出(rethrow)。當(dāng)捕獲到異常時(shí),如果當(dāng)前函數(shù)無(wú)法處理異常,或希望更上層的函數(shù)處理異常,可以使用 throw; 語(yǔ)句重新拋出異常。這種機(jī)制允許在當(dāng)前 catch 塊中處理一些必要的操作(如資源釋放),然后將異常傳遞給調(diào)用鏈中的更外層函數(shù)進(jìn)行進(jìn)一步處理。 

代碼分析

1. Division 函數(shù)

該函數(shù)實(shí)現(xiàn)了兩個(gè)整數(shù)的除法操作:

  • 輸入:兩個(gè)整數(shù) ab。
  • 功能:如果 b == 0,拋出一個(gè)異常,提示 "除以零錯(cuò)誤"。否則,執(zhí)行除法并返回結(jié)果。
double Division(int a, int b) {
    if (b == 0)  // 檢查除數(shù)是否為零
        throw "Division by zero condition!";  // 拋出異常
    return (double)a / (double)b;  // 返回除法結(jié)果
}

 2. Func 函數(shù)

該函數(shù)執(zhí)行除法操作并演示異常的重新拋出。主要有以下幾個(gè)步驟:

  • 輸入:從用戶讀取兩個(gè)整數(shù) lentime。
  • 功能:調(diào)用 Division 函數(shù)進(jìn)行除法計(jì)算。如果發(fā)生除以零錯(cuò)誤,則捕獲異常并執(zhí)行一些清理操作(如釋放動(dòng)態(tài)分配的內(nèi)存)。

catch (...) 捕獲所有類型的異常。

delete[] array; 釋放在 Func 函數(shù)中動(dòng)態(tài)分配的內(nèi)存。

然后,throw; 重新拋出異常,將其傳遞到 main 函數(shù)中的 catch 塊處理。

void Func() {
    int* array = new int[10];  // 動(dòng)態(tài)分配內(nèi)存
    try {
        int len, time;
        cin >> len >> time;  // 從用戶輸入獲取兩個(gè)整數(shù)
        cout << Division(len, time) << endl;  // 調(diào)用Division進(jìn)行除法操作
    } catch (...) {
        // 捕獲所有異常
        cout << "delete []" << array << endl;
        delete[] array;  // 釋放內(nèi)存
        throw;  // 重新拋出異常
    }
    // 在異常未發(fā)生時(shí)釋放內(nèi)存
    cout << "delete []" << array << endl;
    delete[] array;
}

 3. main 函數(shù)

main 函數(shù)包含了一個(gè) try-catch 塊,負(fù)責(zé)捕獲從 Func 函數(shù)傳遞上來(lái)的異常:

  • 捕獲 const char* 類型的異常(即 Division by zero condition! 異常)。
  • 打印異常信息。
int main() {
    try {
        Func();  // 調(diào)用Func執(zhí)行操作
    } catch (const char* errmsg) {  // 捕獲字符串類型的異常
        cout << errmsg << endl;  // 打印異常信息
    }
    return 0;
}

 工作流程與邏輯

  • 執(zhí)行 main 函數(shù),調(diào)用 Func()。
  • Func 中:
    • 從用戶輸入 lentime,調(diào)用 Division(len, time) 執(zhí)行除法。
    • 如果 time == 0,Division 會(huì)拋出 "Division by zero condition!" 異常。
    • catch (...) 捕獲該異常,并執(zhí)行異常處理:
    • 打印正在釋放的動(dòng)態(tài)數(shù)組 array
    • 釋放內(nèi)存(delete[] array)。
    • 使用 throw; 重新拋出異常,將其交給 main 函數(shù)的 catch 塊處理。
    • main 中:
    • 捕獲到異常 "Division by zero condition!",并打印該錯(cuò)誤信息。

異常的重新拋出

throw; 的作用

  • 重新拋出捕獲的異常throw; 可以將當(dāng)前捕獲的異常重新拋出,并將其傳遞給調(diào)用鏈中的更外層 catch 塊進(jìn)行處理。這使得異??梢员簧蠈雍瘮?shù)進(jìn)一步處理。
  • 異常傳遞:在 catch 中進(jìn)行一些必要的處理(如資源釋放、日志記錄等)后,可以選擇將異常交給外層的 catch 塊進(jìn)行后續(xù)處理。

重新拋出場(chǎng)景

  • 資源清理:在 catch 中執(zhí)行資源釋放、日志記錄等操作后,再將異常傳遞給更外層的函數(shù)處理。
  • 中斷異常傳播:有時(shí)候,catch 只需要處理一些臨時(shí)的錯(cuò)誤或簡(jiǎn)單的資源清理工作,而不關(guān)心異常的最終處理,使用 throw; 可以讓更外層的 catch 塊進(jìn)行實(shí)際的錯(cuò)誤處理。
  • 分層處理:復(fù)雜的錯(cuò)誤處理可以分層執(zhí)行。內(nèi)層函數(shù)先進(jìn)行一些清理工作,而具體的錯(cuò)誤處理和恢復(fù)操作交給外層函數(shù)。

總結(jié)

  • 異常重新拋出throw;)是 C++ 異常處理機(jī)制中的一種非常有用的功能。它允許捕獲的異常在某些情況下繼續(xù)傳遞到上層函數(shù),讓更上層的代碼處理實(shí)際的錯(cuò)誤。
  • 在本例中,catch 塊處理了一些臨時(shí)的資源清理工作,然后使用 throw; 將異常重新拋出,最終由 main 函數(shù)中的 catch 塊捕獲并輸出異常信息。
  • 異常處理中的資源管理(例如內(nèi)存釋放)非常重要,因?yàn)樗_保即使發(fā)生異常,動(dòng)態(tài)分配的資源也能夠正確釋放,避免內(nèi)存泄漏等問(wèn)題。

這種機(jī)制可以使異常處理更具靈活性,適應(yīng)不同層級(jí)的錯(cuò)誤處理需求,同時(shí)保證資源的有效釋放。

2.4 異常安全

在 C++ 中,異常安全指的是在出現(xiàn)異常時(shí),確保程序資源管理正確、數(shù)據(jù)一致性不被破壞。構(gòu)造函數(shù)和析構(gòu)函數(shù)是異常安全的關(guān)鍵點(diǎn):

  • 構(gòu)造函數(shù):避免在構(gòu)造函數(shù)中拋出異常,否則對(duì)象可能不完全初始化。使用臨時(shí)對(duì)象或函數(shù)來(lái)避免復(fù)雜操作中出現(xiàn)異常。
  • 析構(gòu)函數(shù):盡量不要在析構(gòu)函數(shù)中拋出異常,因?yàn)檫@可能導(dǎo)致資源泄漏或程序崩潰。如果必須處理異常,捕獲并避免傳播。
  • 資源管理中的異常:在動(dòng)態(tài)內(nèi)存分配(new)和鎖管理中,異??赡軐?dǎo)致內(nèi)存泄漏或死鎖。
  • AII(資源獲取即初始化)模式能自動(dòng)管理資源,確保異常發(fā)生時(shí)正確釋放資源。
  • 智能指針:使用智能指針(如 std::unique_ptr)可以自動(dòng)管理內(nèi)存,避免內(nèi)存泄漏。
  • RAII 和智能指針是解決異常安全問(wèn)題的重要工具,它們通過(guò)在對(duì)象生命周期內(nèi)自動(dòng)管理資源來(lái)確保代碼的穩(wěn)定性。

2.5 異常規(guī)范

1. 異常規(guī)格說(shuō)明的目的是為了讓函數(shù)使用者知道該函數(shù)可能拋出的異常有哪些。 可以在函數(shù)的

后面接throw(類型),列出這個(gè)函數(shù)可能拋擲的所有異常類型。

2. 函數(shù)的后面接throw(),表示函數(shù)不拋異常。

3. 若無(wú)異常接口聲明,則此函數(shù)可以拋擲任何類型的異常。 

// 這里表示這個(gè)函數(shù)會(huì)拋出A/B/C/D中的某種類型的異常
void fun() throw(A,B,C,D);
// 這里表示這個(gè)函數(shù)只會(huì)拋出bad_alloc的異常
void* operator new (std::size_t size) throw (std::bad_alloc);
// 這里表示這個(gè)函數(shù)不會(huì)拋出異常
void* operator delete (std::size_t size, void* ptr) throw();
// C++11 中新增的noexcept,表示不會(huì)拋異常
thread() noexcept;
thread (thread&& x) noexcept;

3. 自定義異常體系 ????

在 C++ 中,自定義異常體系指的是定義自己的異常類,用于表示特定類型的錯(cuò)誤或異常情況。這樣可以使異常處理更具可讀性和靈活性,方便區(qū)分不同類型的錯(cuò)誤。

3.1  自定義異常類

自定義異常類通常繼承自標(biāo)準(zhǔn)庫(kù)中的 std::exception 類,或者更常見(jiàn)的是直接繼承自 std::runtime_errorstd::logic_error。

基本步驟:

  • 繼承 std::exception 或其子類:自定義異常類應(yīng)繼承自 std::exceptionstd::runtime_error,并重寫構(gòu)造函數(shù)來(lái)傳遞錯(cuò)誤消息。
  • 添加構(gòu)造函數(shù)和成員函數(shù):可以添加自定義的構(gòu)造函數(shù),用來(lái)初始化異常信息。
#include <iostream>
#include <stdexcept>
#include <string>
// 自定義異常類,繼承自 std::runtime_error
class MyException : public std::runtime_error {
public:
    MyException(const std::string& message) 
        : std::runtime_error(message) {}  // 調(diào)用基類構(gòu)造函數(shù)
};
void testFunction() {
    throw MyException("Something went wrong!");
}
int main() {
    try {
        testFunction();
    } catch (const MyException& e) {
        std::cout << "Caught MyException: " << e.what() << std::endl;
    } catch (const std::exception& e) {
        std::cout << "Caught std::exception: " << e.what() << std::endl;
    }
    return 0;
}

3.2  自定義多個(gè)異常類型

可以創(chuàng)建不同的異常類型來(lái)表示不同的錯(cuò)誤情境。每種異常類型可以有不同的錯(cuò)誤信息,或不同的邏輯處理

class FileNotFoundException : public std::runtime_error {
public:
    FileNotFoundException(const std::string& filename)
        : std::runtime_error("File not found: " + filename), filename(filename) {}
    const std::string& getFilename() const { return filename; }
private:
    std::string filename;
};
class InvalidInputException : public std::invalid_argument {
public:
    InvalidInputException(const std::string& message)
        : std::invalid_argument(message) {}
};
// 使用示例
try {
    throw FileNotFoundException("data.txt");
} catch (const FileNotFoundException& e) {
    std::cout << e.what() << " Filename: " << e.getFilename() << std::endl;
}

3.3. 捕獲自定義異常

try-catch 塊中捕獲自定義異常時(shí),應(yīng)該使用適當(dāng)?shù)漠惓n愋筒东@,確保正確處理特定的錯(cuò)誤。

try {
    throw InvalidInputException("Invalid input provided");
} catch (const InvalidInputException& e) {
    std::cout << "Caught InvalidInputException: " << e.what() << std::endl;
} catch (const std::exception& e) {
    std::cout << "Caught a generic exception: " << e.what() << std::endl;
}

3.4 異常層次結(jié)構(gòu)設(shè)計(jì)

  • 基類std::exceptionstd::runtime_error 用作基類,定義通用的接口(如 what())。
  • 子類:可以為每種具體錯(cuò)誤類型創(chuàng)建子類,繼承基類并擴(kuò)展功能。

這種設(shè)計(jì)方式使得異常體系更加清晰、可擴(kuò)展。

總結(jié)

自定義異常體系的核心是通過(guò)繼承現(xiàn)有的異常類(如 std::exceptionstd::runtime_error)來(lái)創(chuàng)建符合特定需求的異常類型。這樣可以方便地進(jìn)行異常區(qū)分,幫助編寫更具表現(xiàn)力和可維護(hù)性的代碼。

4.C++標(biāo)準(zhǔn)庫(kù)的異常體系 ????

C++ 提供了一系列標(biāo)準(zhǔn)的異常,定義在 中,我們可以在程序中使用這些標(biāo)準(zhǔn)的異常。它們是以父子類層次結(jié)構(gòu)組織起來(lái)的,如下所示:

說(shuō)明:實(shí)際中我們可以可以去繼承exception類實(shí)現(xiàn)自己的異常類。但是實(shí)際中很多公司像上面一樣自己定義一套異常繼承體系。因?yàn)镃++標(biāo)準(zhǔn)庫(kù)設(shè)計(jì)的不夠好用

int main()
{
try{
vector<int> v(10, 5);
// 這里如果系統(tǒng)內(nèi)存不夠也會(huì)拋異常
v.reserve(1000000000);
// 這里越界會(huì)拋異常
v.at(10) = 100;
}
catch (const exception& e) // 這里捕獲父類對(duì)象就可以
{
cout << e.what() << endl;
}
catch (...)
{
cout << "Unkown Exception" << endl;
}
return 0;
}

5.異常的優(yōu)缺點(diǎn)????

C++異常的優(yōu)點(diǎn):

1. 異常對(duì)象定義好了,相比錯(cuò)誤碼的方式可以清晰準(zhǔn)確的展示出錯(cuò)誤的各種信息,甚至可以包

含堆棧調(diào)用的信息,這樣可以幫助更好的定位程序的bug。

2. 返回錯(cuò)誤碼的傳統(tǒng)方式有個(gè)很大的問(wèn)題就是,在函數(shù)調(diào)用鏈中,深層的函數(shù)返回了錯(cuò)誤,那

么我們得層層返回錯(cuò)誤,最外層才能拿到錯(cuò)誤,具體看下面的詳細(xì)解釋。

// 1.下面這段偽代碼我們可以看到ConnnectSql中出錯(cuò)了,先返回給ServerStart,
ServerStart再返回給main函數(shù),main函數(shù)再針對(duì)問(wèn)題處理具體的錯(cuò)誤。
// 2.如果是異常體系,不管是ConnnectSql還是ServerStart及調(diào)用函數(shù)出錯(cuò),都不用檢查,因
為拋出的異常異常會(huì)直接跳到main函數(shù)中catch捕獲的地方,main函數(shù)直接處理錯(cuò)誤。
int ConnnectSql()
{
// 用戶名密碼錯(cuò)誤
if (...)
return 1;
// 權(quán)限不足
if (...)
return 2;
}
int ServerStart() {
if (int ret = ConnnectSql() < 0)
return ret;
int fd = socket()
if(fd < 0)
return errno;
}
int main()
{
if(ServerStart()<0)
...
return 0;
}

3. 很多的第三方庫(kù)都包含異常,比如boost、gtest、gmock等等常用的庫(kù),那么我們使用它們

也需要使用異常。

4. 部分函數(shù)使用異常更好處理,比如構(gòu)造函數(shù)沒(méi)有返回值,不方便使用錯(cuò)誤碼方式處理。比如

T& operator這樣的函數(shù),如果pos越界了只能使用異?;蛘呓K止程序處理,沒(méi)辦法通過(guò)返回

值表示錯(cuò)誤。

C++異常的缺點(diǎn):

1. 異常會(huì)導(dǎo)致程序的執(zhí)行流亂跳,并且非常的混亂,并且是運(yùn)行時(shí)出錯(cuò)拋異常就會(huì)亂跳。這會(huì)

導(dǎo)致我們跟蹤調(diào)試時(shí)以及分析程序時(shí),比較困難。

2. 異常會(huì)有一些性能的開銷。當(dāng)然在現(xiàn)代硬件速度很快的情況下,這個(gè)影響基本忽略不計(jì)。

3. C++沒(méi)有垃圾回收機(jī)制,資源需要自己管理。有了異常非常容易導(dǎo)致內(nèi)存泄漏、死鎖等異常

安全問(wèn)題。這個(gè)需要使用RAII來(lái)處理資源的管理問(wèn)題。學(xué)習(xí)成本較高。

4. C++標(biāo)準(zhǔn)庫(kù)的異常體系定義得不好,導(dǎo)致大家各自定義各自的異常體系,非常的混亂。

5. 異常盡量規(guī)范使用,否則后果不堪設(shè)想,隨意拋異常,外層捕獲的用戶苦不堪言。所以異常

規(guī)范有兩點(diǎn):

  • 一、拋出異常類型都繼承自一個(gè)基類。
  • 二、函數(shù)是否拋異常、拋什么異常,都使用 func() throw();的方式規(guī)范化。

總結(jié):異??傮w而言,利大于弊,所以工程中我們還是鼓勵(lì)使用異常的。另外OO的語(yǔ)言基本都是用異常處理錯(cuò)誤,這也可以看出這是大勢(shì)所趨。

到此這篇關(guān)于C++ 異常處理機(jī)制與自定義異常體系的文章就介紹到這了,更多相關(guān)C++ 異常處理機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論