如何自定義C++異常類 繼承std exception實(shí)現(xiàn)用戶異常

自定義異常類能提高異常信息的語(yǔ)義性和可識(shí)別性,便于區(qū)分不同模塊或業(yè)務(wù)邏輯的異常情況。1. 繼承 std::exception 或其派生類,并重寫(xiě) what() 方法;2. 構(gòu)造函數(shù)中接收并保存錯(cuò)誤信息,what() 必須為 const noexcept 且返回成員變量;3. 可擴(kuò)展錯(cuò)誤碼等附加信息,通過(guò)新增成員函數(shù)獲取;4. 實(shí)際使用時(shí)應(yīng)避免在 what() 中返回局部變量指針,避免復(fù)雜資源管理,建議設(shè)計(jì)異常類層級(jí)結(jié)構(gòu)以便按需捕獲。

如何自定義C++異常類 繼承std exception實(shí)現(xiàn)用戶異常

c++ 中,自定義異常類是一種常見(jiàn)的做法,特別是在大型項(xiàng)目中,能幫助我們更清晰地定位錯(cuò)誤來(lái)源。標(biāo)準(zhǔn)庫(kù)中的 std::exception 是所有標(biāo)準(zhǔn)異常的基類,通過(guò)繼承它,我們可以創(chuàng)建自己的異常類。

如何自定義C++異常類 繼承std exception實(shí)現(xiàn)用戶異常


為什么需要自定義異常類?

C++ 標(biāo)準(zhǔn)庫(kù)已經(jīng)提供了一些異常類,比如 std::runtime_Error、std::logic_error 等,但它們通常只能表達(dá)通用的錯(cuò)誤類型。當(dāng)我們開(kāi)發(fā)復(fù)雜系統(tǒng)時(shí),往往需要區(qū)分不同模塊或業(yè)務(wù)邏輯的異常情況。

如何自定義C++異常類 繼承std exception實(shí)現(xiàn)用戶異常

舉個(gè)例子:一個(gè)網(wǎng)絡(luò)請(qǐng)求模塊拋出的異常和一個(gè)文件讀寫(xiě)模塊的異常,雖然都屬于運(yùn)行時(shí)錯(cuò)誤,但它們代表的含義完全不同。如果我們用同一個(gè)類型的異常來(lái)表示,后續(xù)捕獲處理時(shí)就很難判斷具體問(wèn)題。

立即學(xué)習(xí)C++免費(fèi)學(xué)習(xí)筆記(深入)”;

所以,自定義異常類的核心目的就是提高異常信息的語(yǔ)義性和可識(shí)別性。

如何自定義C++異常類 繼承std exception實(shí)現(xiàn)用戶異常


如何繼承 std::exception 實(shí)現(xiàn)自定義異常

要?jiǎng)?chuàng)建一個(gè)自定義異常類,最直接的方法是繼承 std::exception 或其派生類(如 std::runtime_error),并重寫(xiě)虛函數(shù) what()。

#include <exception> #include <string> #include <iostream>  class MyException : public std::exception { private:     std::string msg; public:     explicit MyException(const std::string& message) : msg(message) {}      const char* what() const noexcept override {         return msg.c_str();     } };

使用方式如下:

try {     throw MyException("這是一個(gè)自定義異常"); } catch (const std::exception& e) {     std::cout << "捕獲到異常: " << e.what() << std::endl; }

需要注意幾點(diǎn):

  • 構(gòu)造函數(shù)接受錯(cuò)誤信息,并保存為成員變量。
  • what() 函數(shù)必須是 const noexcept 的。
  • 返回的字符串不能是局部變量,否則會(huì)引發(fā)未定義行為。

自定義帶錯(cuò)誤碼的異常類

有時(shí)候除了描述性的信息,我們還需要附加一些結(jié)構(gòu)化的數(shù)據(jù),比如錯(cuò)誤碼。這時(shí)候可以在異常類中加入額外字段。

class MyErrorCodeException : public std::exception { private:     std::string msg;     int errorCode; public:     MyErrorCodeException(const std::string& message, int code)         : msg(message), errorCode(code) {}      const char* what() const noexcept override {         return msg.c_str();     }      int code() const noexcept {         return errorCode;     } };

使用示例:

try {     throw MyErrorCodeException("數(shù)據(jù)庫(kù)連接失敗", 1001); } catch (const MyErrorCodeException& e) {     std::cout << "錯(cuò)誤碼:" << e.code() << ", 描述:" << e.what() << std::endl; }

這種方式適合需要根據(jù)錯(cuò)誤碼做進(jìn)一步處理的情況,比如日志記錄、界面提示等。


常見(jiàn)注意事項(xiàng)與建議

在實(shí)際開(kāi)發(fā)中,使用自定義異常時(shí)要注意以下幾點(diǎn):

  • 不要在 what() 中返回臨時(shí)字符串指針,比如 “Error” 或者函數(shù)內(nèi)的局部數(shù)組。
  • 盡量避免在異常對(duì)象中包含復(fù)雜資源管理邏輯,比如打開(kāi)文件、分配內(nèi)存等,以免在拋出異常時(shí)造成二次異常。
  • 如果你有多個(gè)模塊都需要自定義異常,可以考慮設(shè)計(jì)一個(gè)異常類的層級(jí)結(jié)構(gòu),例如:
    • BaseException
      • NetworkException
      • FileException
      • DatabaseException
  • 這樣在 catch 時(shí)就可以按需捕獲特定子類。

基本上就這些。繼承 std::exception 來(lái)實(shí)現(xiàn)用戶異常并不復(fù)雜,但細(xì)節(jié)上容易忽略,尤其是在字符串生命周期和異常安全方面。只要按照規(guī)范編寫(xiě),就能寫(xiě)出清晰可靠的異常類。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊8 分享