C++?異常處理機(jī)制與自定義異常體系處理方式
前言??????
在程序開發(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ò)使用 throw
和 catch
,程序可以優(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ù)
a
和b
。 - 功能:如果
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ù)
len
和time
。 - 功能:調(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
中:- 從用戶輸入
len
和time
,調(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_error
或 std::logic_error
。
基本步驟:
- 繼承
std::exception
或其子類:自定義異常類應(yīng)繼承自std::exception
或std::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::exception
或std::runtime_error
用作基類,定義通用的接口(如what()
)。 - 子類:可以為每種具體錯(cuò)誤類型創(chuàng)建子類,繼承基類并擴(kuò)展功能。
這種設(shè)計(jì)方式使得異常體系更加清晰、可擴(kuò)展。
總結(jié)
自定義異常體系的核心是通過(guò)繼承現(xiàn)有的異常類(如 std::exception
或 std::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)文章
模擬實(shí)現(xiàn)C語(yǔ)言中的內(nèi)存管理
這篇文章主要內(nèi)容是模擬C語(yǔ)言中的內(nèi)存管理,需要的朋友可以參考下2015-07-07數(shù)據(jù)結(jié)構(gòu)之AVL樹詳解
這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu)之AVL樹詳解,本文非常細(xì)致的講解了AVL樹的基礎(chǔ)知識(shí)、AVL樹的旋轉(zhuǎn)操作、AVL數(shù)的插入和刪除操作等,需要的朋友可以參考下2014-08-08sqlserver,sqlite,access數(shù)據(jù)庫(kù)鏈接字符串整理
本節(jié)主要整理sqlserver,sqlite,access數(shù)據(jù)庫(kù)鏈接字符串,有需要的朋友可以參考下2014-07-07C語(yǔ)言實(shí)現(xiàn)Linux下的socket文件傳輸實(shí)例
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)Linux下的socket文件傳輸?shù)姆椒?較為詳細(xì)的分析了C語(yǔ)言文件Socket文件傳輸客戶端與服務(wù)器端相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2015-06-06c++實(shí)現(xiàn)十進(jìn)制轉(zhuǎn)換成16進(jìn)制示例
這篇文章主要介紹了c++實(shí)現(xiàn)十進(jìn)制轉(zhuǎn)換成16進(jìn)制示例,需要的朋友可以參考下2014-05-05C語(yǔ)言字母轉(zhuǎn)換大小寫的3種方法圖文詳解
我們?cè)贑語(yǔ)言入門的時(shí)候都會(huì)遇到要求寫大小寫轉(zhuǎn)換的題目,所以下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言字母轉(zhuǎn)換大小寫的3種方法,文中給了詳細(xì)的代碼示例,需要的朋友可以參考下2023-10-10淺談c++調(diào)用python鏈接的問(wèn)題及解決方法
下面小編就為大家?guī)?lái)一篇淺談c++調(diào)用python鏈接的問(wèn)題及解決方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03深入Windows下的回車是回車換行(\r\n)還是換行回車(\n\r)的詳解
本篇文章對(duì)Windows下的回車是回車換行(\r\n)還是換行回車(\n\r)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05