• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 45,  comments - 232,  trackbacks - 0
            ???我覺得C++中使用異常在使用中最大的不方便就是在拋出異常的時候沒有位置信息,當程序到一定規模的時候,也很難確定異常從那里拋出,又在那里捕獲的,不利于程序的調試。而在C#中,我發現它的異常的功能太強大了,可以確定異常的位置和捕獲的位置,但它是靠CLR的功能實現的。那么我們怎么在C++中實現這個功能呢?
            ???下面我就為大家介紹我寫的可以獲得拋出異常位置和捕獲異常位置的異常類。該類使用標準C++實現,繼承標準異常exception。你也可以按照這個思路實現一個MFC的版本。我在使用的時候就是使用兩個不同的版本。MFC的版本的功能要強大一點,它內置了Win32錯誤代碼轉換錯誤信息的轉換函數,為程序提供更強大的異常處理功能。
            功能都在兩個主要的宏里面實現:
            1.拋出異常
            // throw?a?comm_exception?that?contains?throw?position?information
            #define ?THROW_EX(what)?\
            ????
            throw ?comm_exception(what,?__FILE__,__FUNCTION__,__LINE__);
            這樣在拋出異常的時候,就把文件,函數,行號信息等信息加入到異常類中。
            2.捕獲異常
            // set?the?position?information?of?catching?the?comm_exception?
            #define ?SET_CATCH_POS(comm_ex)?\
            ????comm_ex.set_catch_file(__FILE__);\
            ????comm_ex.set_catch_function(__FUNCTION__);\
            ????comm_ex.set_catch_line(__LINE__);
            當使用catch捕獲到異常的時候,就通過這個宏設置它的捕獲位置 。
            try
            {
            ??
            ??THROW_EX(
            " there?is?a?exception\n " );
            }
            catch (more_exception? &
            e)
            {
            ??SET_CATCH_POS(e);
            ??std::cout << e;
            }

            比如一個ADO鏈接數據庫的異常輸出為:

            what:??? [DBNETLIB][ConnectionOpen (Connect()).]SQL Server 不存在或拒絕訪問。
            code:? -1
            throw exception at:-----------------
            file:??? f:\tt messenger\v0.7\adodb\adoconn.cpp
            function:C2217::Data::CAdoConn::Open
            line:??? 71
            catch excetion at:------------------
            file:??? e:\項目\tt messenger v0.7\code\server\adodb\adodb.cpp
            function:main
            line:??? 98

            頭文件如下:
            /* ****************************************************************************
            *?Copyright(c)?2003-2005,?C2217?Studio
            *?
            *?Name?of?the?File:????????????comm_exception.h
            *?Summary:????????????????????
            standerd?exception?that?can?get?throwing?position?
            and?catching?position?like?exception?in?.NET?
            *?Current?Version:????????????1.2
            *?Author:????????????????????DengYangjun
            *?Email:????????????????????dyj057@gmail.com
            *?Created?Date:????????????April?30,?2005
            *?Finished?Date:????????????July??13,?2005
            *
            *?Substitutional?Version:????????
            *?Note:
            ????????????1.You?can?use?it?freely,?but?reserve?the?copyright?
            ????????????and?the?author?information
            *?History:????????
            *?Modify?Date:????????????????2005-5-9
            *????????????????????????????version?1.1
            *????????????????????????????Support?MFC?and?Get?Error?message
            *?Modify?Date:????????????????2005-7-13
            *????????????????????????????version?1.2
            *????????????????????????????Rename?as?comm_exception,?it?is?can?used?in?STD?C++
            *????????????????????????????2005-8-16
            *????????????????????????????Add?Error?Code?and?macro?THROW_MY_CODE
            *????????????????????????????
            *****************************************************************************
            */

            #pragma??once

            #ifndef????IBMS_STDLIB_COMM_EXCEPTION
            #define ????IBMS_STDLIB_COMM_EXCEPTION

            #include?
            < exception >
            #include?
            < string >
            #include?
            < ostream >
            #include?
            < iomanip >
            using ? namespace ?std;

            #ifndef?__FUNCTION__
            #define ?__FUNCTION__?"Unkown"

            #endif

            namespace ?C2217
            {
            namespace
            ?StdLib
            {
            class
            ?comm_exception
            ????:
            public
            ?exception
            {
            public
            :
            ????comm_exception(
            string ?what,? string ?throw_file = ""
            ,?
            ????????
            string ?throw_function = "" ,? int ?throw_line =- 1
            )
            ????????:m_what(what),m_throw_file(throw_file),
            ????????m_throw_function(throw_function),m_throw_line(throw_line),m_catch_line(
            - 1
            ),
            ????????m_error_code(
            - 1
            ){}

            ????comm_exception(
            int ?code, string ?what = "" ,? string ?throw_file = ""
            ,?
            ????????????
            string ?throw_function = "" ,? int ?throw_line =- 1
            )
            ????????????:m_what(what),m_throw_file(throw_file),
            ????????????m_throw_function(throw_function),m_throw_line(throw_line),m_catch_line(
            - 1
            ),
            ????????????m_error_code(code){}
            ????
            ????
            virtual ? ~ comm_exception( void
            ){}

            ????
            virtual ? const ? char ? * what()? const ? throw ?()?{? return
            ?m_what.c_str();?}

            ????inline?
            const ? char ? * get_throw_file()? const
            ?
            ????{
            ????????
            return
            ?m_throw_file.c_str();
            ????}
            ????inline?
            const ? char ? * get_throw_function()? const

            ????{
            ????????
            return ?m_throw_function.c_str();
            ????}
            ????inline?
            int ??get_throw_line()? const

            ????{
            ????????
            return ?m_throw_line;
            ????}
            ????inline?
            void ?set_catch_file( const ? char ? *
            catch_file)
            ????{
            ????????m_catch_file?
            =
            ?catch_file;
            ????}
            ????inline?
            void ?set_catch_function( const ? char ? *
            catch_function)
            ????{
            ????????m_catch_function?
            =
            ?catch_function;
            ????}
            ????inline?
            void ?set_catch_line( int
            ?catch_line)
            ????{
            ????????m_catch_line?
            =
            ?catch_line;
            ????}
            ????inline?
            const ? char ? * get_catch_file()? const
            ?
            ????{
            ????????
            return
            ?m_catch_file.c_str();
            ????}
            ????inline?
            const ? char ? * get_catch_function()? const
            ?
            ????{
            ????????
            return
            ?m_catch_function.c_str();
            ????}
            ????inline?
            int ?get_catch_line()? const
            ?
            ????{
            ????????
            return
            ?m_catch_line;
            ????}
            ????inline?
            int ?get_error_code()? const

            ????{
            ????????
            return ?m_error_code;
            ????}

            ????
            string ?str()? const
            ;

            protected
            :
            ????
            string
            ?m_what;
            ????
            string
            ?m_throw_file;
            ????
            string
            ?m_throw_function;
            ????
            int
            ?m_throw_line;

            ????
            string
            ?m_catch_file;
            ????
            string
            ?m_catch_function;
            ????
            int
            ?m_catch_line;
            ????
            int
            ?m_error_code;
            };?
            //
            end?of?class?comm_exception

            // override??operator?<<?for?class?type?comm_exception

            ostream? & ? operator ? << ?(ostream? & out ,? const ?comm_exception? & ?e);

            // throw?a?comm_exception?that?contains?throw?position?information

            #define ?THROW_EX(what)?\
            ????
            throw ?comm_exception(what,?__FILE__,__FUNCTION__,__LINE__);

            // throw?a?comm_exception?that?contians?a?error?code

            #define ?THROW_MY_CODE(errorCode)?\
            ????
            throw ?comm_exception((errorCode),? "" ,?__FILE__,?__FUNCTION__,?__LINE__?);

            // throw?a?comm_exception?that?conts?a?error?code?and?what?

            #define ?THROW_MY_CODE0(errorCode,what)?\
            ????
            throw ?comm_exception((errorCode),?what,__FILE__,?__FUNCTION__,?__LINE__?);

            // throw?a?exception?that?derived?from?comm_exception

            #define ?THROW_EX_TYPE(type,?what)?\
            ????
            throw ?type(what,?__FILE__,__FUNCTION__,__LINE__);

            // throw?a?comm_exception?that?contians?a?error?code

            #define ?THROW_MY_CODE_TYPE(type,errorCode)?\
            ????
            throw ?type((errorCode),? "" ,?__FILE__,?__FUNCTION__,?__LINE__?);

            // throw?a?exception?that?derived?from?comm_exception

            #define ?THROW_MY_CODE0_TYPE(type,errorCode,what)?\
            ????
            throw ?type((errorCode),?what,__FILE__,?__FUNCTION__,?__LINE__?);

            // set?the?position?information?of?catching?the?comm_exception?

            #define ?SET_CATCH_POS(comm_ex)?\
            ????comm_ex.set_catch_file(__FILE__);\
            ????comm_ex.set_catch_function(__FUNCTION__);\
            ????comm_ex.set_catch_line(__LINE__);

            #ifdef?_DEBUG
            #define ?DEBUG_ONLY(f)??????(f)
            #else ?
            #define ?DEBUG_ONLY(f)??????((void)0)
            #endif

            }?
            // End?of?namespace?C2217
            }? // End?of?namespace?StdLib
            #endif
            實現文件如下:

            #include?
            " stdafx.h "
            #include?
            " comm_exception.h "
            #include?
            < sstream >
            using ? namespace ?std;

            namespace
            ?C2217
            {
            namespace
            ?StdLib
            {
            ????ostream?
            & ? operator ? << ?(ostream? & out ,? const ?comm_exception? &
            ?e)
            ????{
            ????????
            out << ? " what:???? " ? << e.what() <<
            endl
            ????????????
            << ? " code:????? " ? << e.get_error_code()? <<
            endl
            ????????????
            << ? " throw?exception?at:----------------- " ? <<
            ?endl
            ????????????
            << ? " file:???? " ? << ?e.get_throw_file()? <<
            endl
            ????????????
            << ? " function: " ? << ?e.get_throw_function()? <<
            endl
            ????????????
            << ? " line:???? " ? << e.get_throw_line() <<
            endl
            ????????????
            << ? " catch?excetion?at:------------------ " ? <<
            ?endl
            ????????????
            << ? " file:???? " ? << ?e.get_catch_file() <<
            endl
            ????????????
            << ? " function: " ? << ?e.get_catch_function() <<
            endl
            ????????????
            << ? " line:???? " ? << e.get_catch_line() <<
            endl;
            ????????
            return ? out
            ;
            ????}

            ????
            string ?comm_exception::str()? const
            ?
            ????{
            ????????stringstream?ss;
            ????????ss?
            << ? * this
            ;
            ????????
            return
            ?ss.str();
            ????}
            }
            }
            與C#中的異常類比較,它少了異常擴散的路徑。
            注意:源程序在Windows XP professional + SP2, Visual .NET 2003 環境下編譯通過。
            posted on 2007-01-24 09:07 天下無雙 閱讀(10754) 評論(5)  編輯 收藏 引用 所屬分類: C/C++

            FeedBack:
            # re: 可獲得拋出位置和捕獲位置的C++異常類[未登錄]
            2007-01-29 12:56 | hdqqq
            這個其實使用了編譯器內建的__FILE__,和 __LINE__宏,在編譯器就確定了的,上面的代碼來說,如果在某個函數中處理了異常并顯示信息,以后不管這個函數在那里被調用,顯示的異常信息都是一樣的. 象下面

            void excep_handle(...)
            {
            try {
            ...
            THROW_EX( " there is a exception\n " );
            } catch (more_exception & e) {
            SET_CATCH_POS(e);
            std::cout << e;
            }
            }

            而調用的函數是這樣的
            void test()
            {
            int i,j,k;
            for (i = 0; i < 100; i++) {
            excep_handle(...)
            for (j = 0; j < 100; j++) {
            excep_handle(...)
            for(k = 0; k < 100; k++) {
            excep_handle(...)
            }
            }
            }
            }

            上面的代碼,不管在那層循環的調用中,異常彈出的都是同一個文件和同一個行數無法知道具體是在那一層出現的異常.  回復  更多評論
              
            # re: 可獲得拋出位置和捕獲位置的C++異常類[未登錄]
            2007-01-29 13:18 | hdqqq
            所以還需要一個附加機制來記錄程序的運行棧,可以象這樣
            #ifdef _DEBUG
            struct _run_stack {
            static std::stack< std::string > _debug_stack;
            };
            #endif

            template<typename a>
            std::string make_debug(a pa)
            {
            stringstream ls;
            ls << pa << std::endl;
            return ls.str();
            }

            template<typename a,typename b>
            std::string make_debug(a pa, b pb)
            {
            stringstream ls;
            ls << pa << " " << pb << std::endl;
            return ls.str();
            }
            ...按需要擴充

            struct debug_help {

            template<typename a>
            debug_help(a pa) {
            _run_stack::_debug_stack.push(make_debug(pa));
            }
            template<typename a, typename b>
            debug_help(a pa,b pb) {
            _run_stack::_debug_stack.push(make_debug(pa,pb));
            }
            ...按需要擴充

            ~debug_help() {
            _run_stack::_debug_stack.pop();
            }
            };

            -----
            實際使用
            void excepti_func
            {
            #ifdef _DEBUG
            debug_help(__FILE__,__LINE__);
            #endif
            ....
            }

            或者
            void _fd
            {
            int i,j,k;
            for (i = 0; i< 100; i__) {
            debug_help(__FILE__,__LINE__, i);
            for (j = 0; j < 100; j++) {
            debug_help(__FILE__,__LINE__, j);
            for(k = 0; k < 100; k++) {
            debug_help(__FILE__,__LINE__, k);
            }
            }
            }
            }

            出現異常的時候,只要把_run_stack::_debug_stack顯示出來看看就可以了.也可以通過條件編譯,在最終release中將其去掉.  回復  更多評論
              
            # re: 可獲得拋出位置和捕獲位置的C++異常類[未登錄]
            2007-01-29 18:41 | 天下無雙
            你說的這個情況我以前也想過,如果為每個異常都需要一個stack對象,還可以存儲exception的擴散路徑,但對一個異常對象也許顯得太復雜了。
            這個可以根據自己的需求定制一個異常類。  回復  更多評論
              
            # re: 可獲得拋出位置和捕獲位置的C++異常類
            2007-01-31 19:53 | T-Bac
            《Modern C++ Design》  回復  更多評論
              
            # re: 可獲得拋出位置和捕獲位置的C++異常類[未登錄]
            2009-02-11 17:13 | wang
            error: looser throw specifier for `virtual C2217::StdLib::comm_exception::~comm_exception()'
            error: overriding `virtual std::exception::~exception() throw ()'

            請問怎么是怎么回事,怎么解決?  回復  更多評論
              

            常用鏈接

            留言簿(15)

            隨筆分類

            隨筆檔案

            相冊

            我的其它領域Blog

            搜索

            •  

            積分與排名

            • 積分 - 205756
            • 排名 - 130

            最新評論

            閱讀排行榜

            評論排行榜

            久久无码中文字幕东京热| 中文字幕久久欲求不满| 亚洲一本综合久久| 69久久夜色精品国产69| 国产69精品久久久久99| 亚洲第一永久AV网站久久精品男人的天堂AV | 久久亚洲高清综合| 精品一二三区久久aaa片| 久久久久国产精品| 少妇内射兰兰久久| 久久久综合香蕉尹人综合网| 久久久精品国产亚洲成人满18免费网站 | 亚洲国产精品高清久久久| 久久久久人妻一区精品色| 亚洲国产香蕉人人爽成AV片久久 | 国产精品久久久久久久午夜片| 久久久精品久久久久久| 久久一日本道色综合久久| 四虎影视久久久免费| 久久精品国产99久久久| 性做久久久久久久久老女人| 久久久久国产精品熟女影院| 欧美激情精品久久久久久| 久久99精品久久久久久久不卡 | 久久婷婷成人综合色综合| 久久精品亚洲福利| 2021精品国产综合久久| 国产精品99久久久精品无码| 亚洲精品久久久www| 99久久99久久精品国产| 久久久婷婷五月亚洲97号色| 一个色综合久久| 色偷偷91久久综合噜噜噜噜| 国产精品久久久久9999| 亚洲精品国产字幕久久不卡 | 久久精品国产一区二区三区| 99久久er这里只有精品18| 尹人香蕉久久99天天拍| 日韩欧美亚洲综合久久影院Ds | 亚洲国产成人久久综合区| 精品免费久久久久国产一区|