日本好好热aⅴ|国产99视频精品免费观看|日本成人aV在线|久热香蕉国产在线

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
      軟件
      軟件
      文章
      搜索

      首頁編程開發(fā)VC|VC++ → 自己設(shè)計(jì)C++完善的異常處理類

      自己設(shè)計(jì)C++完善的異常處理類

      相關(guān)軟件相關(guān)文章發(fā)表評論 來源:本站整理時(shí)間:2010/10/31 9:24:39字體大。A-A+

      作者:佚名點(diǎn)擊:390次評論:0次標(biāo)簽: 異常處理

      PeStudio編程輔助v8.42 綠色免費(fèi)版
      • 類型:編程輔助大小:699KB語言:英文 評分:5.0
      • 標(biāo)簽:
      立即下載
      我們的異常處理類的features

      如何寫一個(gè)異常處理類是一個(gè)不太容易的事情,最近剛好接觸了一些不錯(cuò)的代碼,看到了一些技巧,這里和大家分享一下。

      一個(gè)相對完善的異常處理類(以及附加的一些東西)應(yīng)該能夠處理下面的一些功能:

      1) 能夠方便的定義異常類的繼承樹

      2) 能夠方便的throw、catch,也就是在代碼中捕獲、處理代碼的部分應(yīng)該更短

      3) 能夠獲取異常出現(xiàn)的源文件的名字、方法的名字、行號

      4) 能夠獲取異常出現(xiàn)的調(diào)用棧并且打印出來

      由于目前我用的平臺是linux,所以里面調(diào)用的一些函數(shù)也只是在linux下面有用。Windows也肯定是具有相應(yīng)的函數(shù)的,具體可能需要去查查

      首先科普一些內(nèi)容:

      1) 對于沒有捕獲的異常(no handler),則會終止程序,調(diào)用terminate()

      2) 在定義函數(shù)的時(shí)候,我們可以在定義的后面加上throw (exception1, exception2…):

          a) 如果沒有寫這一段、則可能拋出任意的異常

          b) 如果寫throw(),則表示函數(shù)不能拋出任意的異常

          c) 如果寫throw(A, B), 表示函數(shù)拋出A、B的異常

      如果拋出的異常不在列表范圍內(nèi),則異常不能被catch,也就會調(diào)用terminate()

      我們構(gòu)想一下我們定義、調(diào)用我們的異常類的時(shí)候是怎樣的一個(gè)情形:

      1) 定義:

      1:class DerivedException : public BaseException

      2: {

      3:public:

      4: MY_DEFINE_EXCEPTION(DerivedException, BaseException);

      5: };

      2) 如何拋出異常

      1: MY_THROW(DerivedException)

      3) 如何catch異常

      1:catch (DerivedException& e)

      2: {

      3: cout<< e.what() << endl;

      4: }

      這個(gè)輸出的內(nèi)容包括錯(cuò)誤的行號、文件名、方法名、和調(diào)用棧的列表

      給出我們異常類的頭文件:

      1:#ifndef EXCEPTION_TEST

      2:#define EXCEPTION_TEST

      3: 

      4:#include

      5:#include

      6: 

      7:#define MY_THROW(ExClass, args...) \

      8:do \

      9: { \

      10: ExClass e(args); \

      11: e.Init(__FILE__, __PRETTY_FUNCTION__, __LINE__); \

      12:throw e; \

      13: } \

      14:while (false)

      15: 

      16:#define MY_DEFINE_EXCEPTION(ExClass, Base) \

      17: ExClass(const std::string& msg = "") throw() \

      18: : Base(msg) \

      19: {} \

      20: \

      21: ~ExClass() throw() {} \

      22: \

      23:/* override */ std::string GetClassName() const \

      24: { \

      25:return #ExClass; \

      26: }

      27: 

      28:class ExceptionBase : public std::exception

      29: {

      30:public:

      31: ExceptionBase(const std::string& msg = "") throw();

      32: 

      33:virtual ~ExceptionBase() throw();

      34: 

      35:void Init(constchar* file, constchar* func, int line);

      36: 

      37:virtual std::string GetClassName() const;

      38: 

      39:virtual std::string GetMessage() const;

      40: 

      41:constchar* what() constthrow();

      42: 

      43:const std::string& ToString() const;

      44: 

      45: std::string GetStackTrace() const;

      46: 

      47:protected:

      48: std::string mMsg;

      49:constchar* mFile;

      50:constchar* mFunc;

      51:int mLine;

      52: 

      53:private:

      54:enum { MAX_STACK_TRACE_SIZE = 50 };

      55:void* mStackTrace[MAX_STACK_TRACE_SIZE];

      56: size_t mStackTraceSize;

      57:mutable std::string mWhat;

      58: };

      59: 

      60:class ExceptionDerived : public ExceptionBase

      61: {

      62:public:

      63: MY_DEFINE_EXCEPTION(ExceptionDerived, ExceptionBase);

      64: };

      65: 

      66:#endif

      這個(gè)頭文件首先定義了兩個(gè)宏,這里先暫時(shí)不管他,我先來解釋一下ExceptionBase,它繼承自std::exception,std::exception里面其實(shí)已經(jīng)提供了一些功能了,但是比較弱,為了實(shí)現(xiàn)我們上文提到的功能,這里只是繼承了std:exception的借口,也就是what()函數(shù)。

      上面的接口應(yīng)該比較好理解,45行的GetStackTrace是打印當(dāng)前的調(diào)用棧,49-51行分別存儲了當(dāng)前出現(xiàn)exception的源文件名,函數(shù)名,行號,54行定義了最大的調(diào)用棧顯示的深度,也就是顯示50行。

      60行顯示了怎樣定義一個(gè)新的異常類,這個(gè)就很方便了,通過MY_DEFINE_EXCEPTION宏去定義了一個(gè)繼承類,詳情見16行,這里不再細(xì)說,我這里想說說7行的MY_THROW宏,使用了3個(gè)內(nèi)置的參數(shù),__FILE__, __LINE__, __PRETTY_FUNCTION__, 他們分別是當(dāng)前的文件名,行號,和函數(shù)名,他們的使用方法是在哪兒出現(xiàn),其相應(yīng)的值就是什么。

      為什么這里要使用MY_THROW宏呢?其實(shí)是為了方便的把行號、文件名等加入進(jìn)來,宏展開的時(shí)候是在一行上的,這樣也使得行號與出錯(cuò)的行號保持一致,而且讓代碼更簡單。

      給出異常類的.cpp文件:

      1:#include <execinfo.h>

      2:#include <stdlib.h>

      3:#include <cxxabi.h>

      4: 

      5:#include

      6:#include

      7: 

      8:#include"exception_test.h"

      9: 

      10:usingnamespace std;

      11: 

      12: ExceptionBase::ExceptionBase(const std::string& msg) throw()

      13: : mMsg(msg),

      14: mFile(""),

      15: mFunc(""),

      16: mLine(-1),

      17: mStackTraceSize(0)

      18: {}

      19: 

      20: ExceptionBase::~ExceptionBase() throw()

      21: {}

      22: 

      23:void ExceptionBase::Init(constchar* file, constchar* func, int line)

      24: {

      25: mFile = file;

      26: mFunc = func;

      27: mLine = line;

      28: mStackTraceSize = backtrace(mStackTrace, MAX_STACK_TRACE_SIZE);

      29: }

      30: 

      31: std::string ExceptionBase::GetClassName() const

      32: {

      33:return"ExceptionBase";

      34: }

      35: 

      36:constchar* ExceptionBase::what() constthrow()

      37: {

      38:return ToString().c_str();

      39: }

      40: 

      41:const std::string& ExceptionBase::ToString() const

      42: {

      43:if (mWhat.empty())

      44: {

      45: stringstream sstr("");

      46:if (mLine > 0)

      47: {

      48: sstr << mFile << "(" << mLine << ")";

      49: }

      50: sstr << ": " << GetClassName();

      51:if (!GetMessage().empty())

      52: {

      53: sstr << ": " << GetMessage();

      54: }

      55: sstr << "\nStack Trace:\n";

      56: sstr << GetStackTrace();

      57: mWhat = sstr.str();

      58: }

      59:return mWhat;

      60: }

      61: 

      62: std::string ExceptionBase::GetMessage() const

      63: {

      64:return mMsg;

      65: }

      66: 

      67: std::string ExceptionBase::GetStackTrace() const

      68: {

      69:if (mStackTraceSize == 0)

      70:return"\n";

      71:char** strings = backtrace_symbols(mStackTrace, 10);

      72:if (strings == NULL) // Since this is for debug only thus

      73:// non-critical, don't throw an exception.

      74:return"\n";

      75: 

      76: std::string result;

      77:for (size_t i = 0; i < mStackTraceSize; ++i)

      78: {

      79: std::string mangledName = strings[i];

      80: std::string::size_type begin = mangledName.find('(');

      81: std::string::size_type end = mangledName.find('+', begin);

      82:if (begin == std::string::npos || end == std::string::npos)

      83: {

      84: result += mangledName;

      85: result += '\n';

      86:continue;

      87: }

      88: ++begin;

      89:int status;

      90:char* s = abi::__cxa_demangle(mangledName.substr(begin, end-begin).c_str(),

      91: NULL, 0, &status);

      92:if (status != 0)

      93: {

      94: result += mangledName;

      95: result += '\n';

      96:continue;

      97: }

      98: std::string demangledName(s);

      99: free(s);

      100:// Ignore ExceptionBase::Init so the top frame is the

      101:// user's frame where this exception is thrown.

      102://

      103:// Can't just ignore frame#0 because the compiler might

      104:// inline ExceptionBase::Init.

      105: result += mangledName.substr(0, begin);

      106: result += demangledName;

      107: result += mangledName.substr(end);

      108: result += '\n';

      109: }

      110: free(strings);

      111:return result;

      112: }

      113: 

      114:/*

      115: * test-main

      116: */

      117:int f2()

      118: {

      119: MY_THROW(ExceptionDerived, "f2 throw");

      120: }

      121:void f1()

      122: {

      123:try

      124: {

      125: f2();

      126: }

      127:catch (ExceptionDerived& e)

      128: {

      129: cout << e.what() << endl;

      130: }

      131: }

      132:int main()

      133: {

      134: f1();

      135: }

      這是函數(shù)的實(shí)現(xiàn)代碼,其他的都比較好理解,67行的GetStackTrace是相對復(fù)雜一點(diǎn)的,里面用backtrace函數(shù)去獲取了當(dāng)前調(diào)用棧的層數(shù),用backtrace_symbols去獲取當(dāng)前調(diào)用棧的符號,而且__cxa_demangle函數(shù)的使用也值得去看看,這里不再細(xì)說了。

      117行后展示了一個(gè)測試代碼,代碼雖然定義比較麻煩,不過使用還是很方便的:)。

        相關(guān)評論

        閱讀本文后您有什么感想? 已有人給出評價(jià)!

        • 8 喜歡喜歡
        • 3 頂
        • 1 難過難過
        • 5 囧
        • 3 圍觀圍觀
        • 2 無聊無聊

        熱門評論

        最新評論

        發(fā)表評論 查看所有評論(0)

        昵稱:
        表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
        字?jǐn)?shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)