我看到这是一个老问题,但我认为在异常宏中打印行的方法存在根本缺陷,我认为我有更好的选择。我假设宏的使用类似于下面的代码:
try {
/// code
throw;
}
catch (...) { __EXCEPTION(aMessage); }
使用这种方法,宏会打印出异常为catch'ed的位置。但对于故障排除和调试为throw'n的位置通常更有用.
要获取该信息,我们可以将__FILE__ 和__LINE__ 宏附加到异常。然而,我们仍然无法完全摆脱宏,但我们至少得到了确切的抛出位置:
#include <iostream>
#include <exception>
#include <string>
#define MY_THROW(msg) throw my_error(__FILE__, __LINE__, msg)
struct my_error : std::exception
{
my_error(const std::string & f, int l, const std::string & m)
: file(f)
, line(l)
, message(m)
{}
std::string file;
int line;
std::string message;
char const * what() const throw() { return message.c_str(); }
};
void my_exceptionhandler()
{
try {
throw; // re-throw the exception and capture the correct type
}
catch (my_error & e)
{
std::cout << "Exception: " << e.what() << " in line: " << e.line << std::endl;
}
}
int main()
{
try {
MY_THROW("error1");
} catch(...) { my_exceptionhandler(); }
}
如果我们愿意使用boost::exception,还有一个额外的改进可能:我们至少可以在我们自己的代码中摆脱宏定义。整个程序变得更短,代码执行和错误处理的位置可以很好地分开:
#include <iostream>
#include <boost/exception/all.hpp>
typedef boost::error_info<struct tag_error_msg, std::string> error_message;
struct error : virtual std::exception, virtual boost::exception { };
struct my_error: virtual error { };
void my_exceptionhandler()
{
using boost::get_error_info;
try {
throw;
}
catch(boost::exception & e)
{
char const * const * file = get_error_info<boost::throw_file>(e);
int const * line = get_error_info<boost::throw_line>(e);
char const * const * throw_func = get_error_info<boost::throw_function>(e);
std::cout << diagnostic_information(e, false)
<< " in File: " << *file << "(" << *line << ")"
" in Function: " << *throw_func;
}
}
int main()
{
try {
BOOST_THROW_EXCEPTION(my_error() << error_message("Test error"));
} catch(...) { my_exceptionhandler(); }
}