vs 2005中有个_THROW宏,在库的代码中经常能看到该宏。该宏定义于 <xstddef> 文件中。
简化的代码如下:
#if _HAS_EXCEPTIONS
#define _THROW(x, y) throw x(y)
#define _RAISE(x) throw (x)
#else /* _HAS_EXCEPTIONS */
#define _THROW(x, y) x(y)._Raise()
#define _RAISE(x) ::std:: _Throw(x)
#endif
_HAS_EXCEPTIONS 宏位于yvals.h
#ifndef _HAS_EXCEPTIONS
#define _HAS_EXCEPTIONS 1 /* predefine as 0 to disable exceptions */
#endif /* _HAS_EXCEPTIONS */
默认情况下是1,则_THROW宏扩展为 throw x(y),否则就是x(y)._Raise()
举个例子:
class failure : public runtime_error
{ // base of all iostreams exceptions
public:
explicit failure(const string &_Message)
: runtime_error(_Message)
{ // construct with message
}
virtual ~failure() _THROW0()
{ // destroy the object
}
#if !_HAS_EXCEPTIONS
protected:
virtual void _Doraise() const
{ // report the exception
_RAISE(*this);
}
#endif /* _HAS_EXCEPTIONS */
};
failure类继承自runtime_error,代表一种运行时异常。 其中有个成员函数_Doraise(),只有在没有定义_HAS_EXCEPTIONS时会有。
_THROW(failure, "can't find the record...");
按照上述规则,如果定义了_HAS_EXCEPTIONS宏,则展开是:
throw failure("cant't find the record..."); // 这种形式很好理解
否则,展开是 failure("can't find the record...")._Raise();
但_Raise()函数似乎并不是failure类的成员函数,应该是继承下来的。沿着继承路径查找,发现exception类中有该成员函数。
void exception::_Raise() const
{ // raise the exception
if (_Raise_handler != 0) // 全局变量
(*_Raise_handler)(*this); // call raise handler if present
_Doraise(); // call the protected virtual
_RAISE(*this); // raise this exception
}
它首先调用一个全局异常处理函数来处理该异常,然后调用_Doraise(),由于该函数是虚函数,所以调用了failure::_Doraise()函数。
再看_Raise宏,在没有定义_HAS_EXCEPTIONS时展开是std::_Throw(),这个函数位于stdthrow.cpp中。
namespace std{
void _Throw(const exception& ex)
{ // report throw exception and die
std::_Debug_message("exception: ", ex.what());
}
}
std::_Debug_message函数也位于stdthrow.cpp中。它将异常信息输出到标准错误流中。
void _Debug_message(const char *s1, const char *s2)
{ // legacy report error and die
::fflush(0);
::fputs(s1, _cpp_stderr);
::fputs(s2 != 0 ? s2 : "unknown", _cpp_stderr);
::fputs("\n", _cpp_stderr);
#if defined(_WIN32_WCE)
::exit(3);
#else
::abort();
#endif
}
ps:调试代码和上述分析不一致,无论_HAS_EXCEPTIONS为何值,好像都一样,迷糊。。。
#define _HAS_EXCEPTIONS 0
#include "stdafx.h"
#include <stdexcept>
using namespace std;
class failure : public runtime_error
{ // base of all iostreams exceptions
public:
explicit failure(const string &_Message)
: runtime_error(_Message)
{ // construct with message
}
virtual ~failure() _THROW0()
{ // destroy the object
}
#if !_HAS_EXCEPTIONS
protected:
virtual void __CLR_OR_THIS_CALL _Doraise() const
{ // report the exception
cout<<"Call _Doraise()"<<endl;
_RAISE(*this);
}
#endif /* _HAS_EXCEPTIONS */
};
int _tmain(int argc, _TCHAR* argv[])
{
_THROW(failure, "can't find the record...");
return 0;
}