如果你有一个大型系统,它会自动显示一个漂亮的窗口来解释捕获的异常,那么能够将错误代码与消息一起显示(用于进一步调查)会很好。但是由于有些函数调用是针对设置错误代码的失败 windows 函数,而有些是未设置错误代码的本地失败函数,我想知道是否有办法检查最后设置的错误代码是否已"检索"。
假设我们有一段代码
if (!CopyFile(("c:foobar.txt", "d:foobar.txt",FALSE))
{
throw FooBarException("bla bla bla");
}
在这里,可以自动将错误代码添加到错误消息中,因为 CopyFile 是一个在失败时设置错误代码的函数。现在,我们可以在 if 语句中"手动"添加错误代码,并将其附加到创建异常时传递的错误字符串中。但是为了不必在现有代码中更改数千个位置,我们可以让 FooBarException 的构造函数自动获取并附加错误代码。但这也提出了问题。
如果某些未设置错误代码的代码导致引发 FooBarException 怎么办?然后,构造函数将 GetLastError 但得到一个可能根本不连接到当前异常的错误代码。
但是,如果 FooBarException 的构造函数可以调用一些 LastErrorRetrived(或类似的东西)并且如果错误代码在它之前已经被检索到,则忽略附加错误代码并假设它与早期错误有关。
现在我明白了,如果一个人在每个可能失败的 windows 函数之后没有实际"检索"错误代码并设置错误代码,这可能会变得混乱。但是,让我们假设这已经完成。
简短回答:不。
GetLastError
返回的值只是一个全局(每线程)对象,不附加任何逻辑。它可以通过GetLastError
、SetLastError
和神秘的RestoreLastError
进入。
恐怕我必须爆料:将错误处理改装到一个没有准备好的系统中是乏味的。
除了实现多个异常类(对于 Win32 错误代码、COM HRESULT
等)并更改每个调用之外,您几乎无能为力。
GetLastError() 只是获取线程的最后一个错误代码值,仅此而已。所以,我相信没有办法知道它是否被叫过一次或几次。而且,我真的认为你不需要。
这里最好的解决方案是创建从某个基类派生的WinAPIException类(例如,std::exception)。在构造函数中,WinAPIException 应该在任何其他 WinAPI 调用之前调用 GetLastError()。它保证错误值不会更改。
if( !CopyFile("c:foobar.txt", "d:foobar.txt",FALSE) )
throw WinAPIException("Houston, we have a WINAPI problem");
如果在非 WinAPI 函数调用后检查结果 - 只需使用其他异常类(派生自同一基类):
if( std::cin.get() < 0 )
throw std::runtime_error("Houston, we have runtime problem");
因此,您可以使用单次尝试...catch 语句来捕获两个异常:
try {
...
} catch( std::exception &e ) {
...
}