我觉得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
天下无双 阅读(10715)
评论(5) 编辑 收藏 引用 所属分类:
C/C++