???我覺得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
天下無雙 閱讀(10753)
評論(5) 編輯 收藏 引用 所屬分類:
C/C++