方便的 HRESULT 到异常转换器






3.63/5 (6投票s)
2005年10月21日
2分钟阅读

47856

244
一种简洁易用的方法,可以将 HRESULT 错误转换为异常,包括文件名和行号。
引言
这个想法源于对 HRESULT Error Check Simplifier By Wanderley Caloni 的扩展,所以我认为他的介绍比我自己写的更好。非常感谢 Wanderley Caloni 撰写这篇文章。
我在这里介绍一下我添加的内容。 上述文章中,有一个类检查 HRESULT
值是否为 SUCCEEDED
。 如果不是,则抛出异常。 添加的功能是,能够显示一个消息框,其中包含行号、文件名和自定义错误消息。
使用代码
请看这个用法示例
if( NULL == ( direct3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) throw MyException(_E("Can't create Direct3D object")); hrToException(_E("Can't get adapter display mode")) = direct3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&Mode);
throw MyException(_E("无法创建 Direct3D 对象"));
是正常的,任何 C++ 开发者都知道,它只是抛出一个异常。
但关键在于下一个示例 hrToException(_E("无法获取适配器显示模式")) = direct3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&Mode);
:它只是意味着,如果函数调用 direct3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&Mode)
的返回值 HRESULT
为 FAILED
,则抛出一个异常,其中包含当前行号、当前文件名以及错误字符串“无法获取适配器显示模式”。
以前的做法是
if(FAILED(direct3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&Mode)) throw MyException("Can't get adapter display mode",__FILE__,__LINE__);
想象一下你的代码中充斥着这种 if
语句 :-)。 至少这个新类可以减轻你的分支逻辑负担。
这是 _E()
宏。 它只是将行号和文件名添加到异常构造函数的参数中,以节省一些输入。
#define _E(str) str##,##__FILE__##,##__LINE__
你的代码应该位于 try
-catch
块中。
#define _MYTRY try {
有一个预定义的 catch
块,用于生成消息框,并节省一些输入。 如果你计划使用更长的错误字符串,可以更改 error[]
的长度。
// the catch statement that shows the message box #define _MYCATCH \ } \ catch(MyException ex) \ { \ char error[255]; \ sprintf(error,"%s ( HRESULT = %i ), file: %s, line: %i" , ex.error_str , ex.hr , ex.file , ex.lineNumber);\ ::MessageBox(hWnd,error , "MyException Caught" , MB_OK); \ exit(E_FAIL); \ }
异常类仅包含这四个信息。
// the exception class struct MyException { ... char* error_str; char* file; int lineNumber; HRESULT hr; };
检查该行
hrToException(_E("Can't get adapter display mode")) = direct3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&Mode);
它的实现方式如下
// the class that throws, if an HRESULT failed class HResultToException { public: HResultToException& operator()(char* error, char* file_name,int line_number) { error_str = error; this->file_name = file_name; this->line_number = line_number; return *this; } void operator=(HRESULT hr) { if(FAILED(hr)) throw MyException(error_str,hr,file_name,line_number); } };
结论
这篇文章只是为了展示一些增强可读性的想法,但缺乏可重用性。 如果有人能使其更具可重用性,我将不胜感激。 无论如何,这篇文章旨在展示一个示例,读者不应该直接使用。 读者应该理解这个想法,并根据自己的需要重新实现它。