说我有:
try { externalLibrary::doSomething(); } catch (std::exception &e) { //yay I kNow what to do } catch (...) { //darn,I've no idea what happened! }
可能有些情况下您会收到异常,并且您不知道来自哪里或为什么 – 在一些没有调试信息的外部库中.有没有办法找到被抛出的东西,或者获得与之相关的任何数据?他们可能在做:
throw myStupidCustomString("here is some really useful information");
但我永远不知道我是否抓住…
在MSVC 2008工作如果重要.
解决方法
因为C是静态类型的,你必须抓住已知的类型.但是,您可以调用外部函数(或一组函数),它们在您调用它们时处理异常类型未知.如果这些处理程序都具有已知类型,那么可以注册它们进行动态尝试.
struct myStupidCustomString { myStupidCustomString(char const *what) : what (what) {} char const *what; }; void throws() { throw myStupidCustomString("here is some really useful information"); } // The external library can provide a function,or you can provide a wrapper,which // extracts information from "unkNown" exception types. std::string extract_from_unkNown_external_exception() { try { throw; } catch (myStupidCustomString &e) { return e.what; } catch (...) { throw; // Rethrow original exception. } }
Use:
void example() { try { throws(); } catch (...) { try { std::string extracted = extract_from_unkNown_external_exception(); std::cout << "extracted: " << extracted << '\n'; } catch (...) { // Chain handlers for other types; e.g. exception types from other libraries. // Or do something generic for the unkNown exception. // Or rethrow the original unkNown exception: throw; } } }
typedef std::string Extract(); std::vector<Extract*> chain (1,&extract_from_unkNown_external_exception); // Chain would normally be initialized using whatever scheme you prefer for // initializing global objects. // A list or other container (including a manual linked list that doesn't // require dynamic allocation) may be more appropriate,depending on how you // want to register and unregister handlers. std::string process_chain() { for (std::vector<Extract*>::iterator x = chain.begin(); x != chain.end(); ++x) { try { return (*x)(); } catch (...) {} // That handler Couldn't handle it. Proceed to next. } throw; // None Could handle it,rethrow original exception. } void example() { try { throws(); } catch (...) { try { std::string extracted = process_chain(); std::cout << "extracted: " << extracted << '\n'; } catch (...) { throw; // Rethrow unkNown exception,or otherwise handle it. } } }
最后,如果您了解实现细节,可以使用它们来提取您的实现暴露的任何其他信息. C 0x也以便携式方式公开了一些细节;看看std :: exception_ptr.