为什么在定义错误/ HRESULT处理/记录时选择或不选择使用宏?
我正在通过接口调用一个错误处理类,因此可以在需要的时间和地点使用Boost共享指针来调用该类。(说实话;我不知道这是否是最好的方法,但我主要是想看看我是否能做到以及它的外观)。即:
typedef std::shared_ptr<iErrorHandling> Error_Handler;
Error_Handler Err_Handler(new ErrHandling);
if (error)
{
Err_Handler->vDX_ERR(ERR_D3D_INIT_SWAP);
}
Run Code Online (Sandbox Code Playgroud)
我开始将类与DirectX一起使用,因为DirectX需要大量的HRESULT处理,因此我被指向使用宏来避免所有if / else语句。我遇到了这个:
#define lengthof(rg) (sizeof(rg)/sizeof(*rg))
inline const char* StringFromError(char* szErr, long nSize, long nErr)
{
_ASSERTE(szErr);
*szErr = 0;
DWORD cb = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, nErr, 0, szErr, nSize, 0);
char szUnk[] = "<unknown>";
if( !cb && nSize >= lengthof(szUnk) ) lstrcpyA(szErr, szUnk);
return szErr;
}
inline HRESULT TraceHR(const char* pszFile, long nLine, HRESULT hr)
{
if( FAILED(hr) )
{
char szErr[128];
char sz[_MAX_PATH + lengthof(szErr) + 64];
wsprintfA(sz, "%s(%d) : error 0x%x: %s\n", pszFile, nLine, hr,
StringFromError(szErr, lengthof(szErr), hr));
OutputDebugStringA(sz);
}
return hr;
}
#ifdef _DEBUG
#define TRACEHR(_hr) TraceHR(__FILE__, __LINE__, _hr)
#else
#define TRACEHR(_hr) _hr
#endif
#define HR(ex) { HRESULT _hr = ex; if(FAILED(_hr)) return TRACEHR(_hr), _hr; }
Run Code Online (Sandbox Code Playgroud)
(摘自:https : //www.sellsbrothers.com/writing/a_young_person.htm)
虽然这对我来说看起来很棒,但我还发现了一些站点,这些站点将宏描述为“邪恶的”,因此应尽量少使用它们。
哪种方法效果更好,为什么?我还没有发现另一种方法吗?
另外; 定义宏__FILE__ __FUNC__ __LINE__
以创建错误日志字符串是否有意义,或者定义自己的特定错误并在头文件中列出它们是否可以接受?
即:
static LPTSTR ERR_D3D_INIT_HW = __T("cD3D::Initialize: Failed to establish hardware.");
static LPTSTR ERR_D3D_INIT_SWAP = __T("cD3D::Initialize: Failed to create the swap device.");
Run Code Online (Sandbox Code Playgroud)
无论哪种方法花费多少时间,哪种性能更好?
宏并不是天生的邪恶。但是,如果使用不当,它们往往会使代码难以阅读,并且可能导致难以调试的错误。由于这些原因,一般建议始终倾向于使用较少的宏。您提出的是两种非常特殊的情况,其中宏很好。
__LINE__
et al的日志/跟踪宏很常见,没有宏就很难(/不可能)达到相同的效果。恕我直言,他们没有错。FAILED(hr)
像宏一样,也很常见,没有错误或很难读懂它们。您可以改用函数,而对于当今的编译器来说,大多数时候都可以内联,但这并非总是如此。FAILED
特别是COM / DirectX的一部分已有二十年了,人们已经习惯了对其进行解析。