65.9K
CodeProject 正在变化。 阅读更多。
Home

方便的 HRESULT 到异常转换器

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.63/5 (6投票s)

2005年10月21日

2分钟阅读

viewsIcon

47856

downloadIcon

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) 的返回值 HRESULTFAILED,则抛出一个异常,其中包含当前行号、当前文件名以及错误字符串“无法获取适配器显示模式”。

以前的做法是

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);
    }
};

结论

这篇文章只是为了展示一些增强可读性的想法,但缺乏可重用性。 如果有人能使其更具可重用性,我将不胜感激。 无论如何,这篇文章旨在展示一个示例,读者不应该直接使用。 读者应该理解这个想法,并根据自己的需要重新实现它。

© . All rights reserved.