Поскольку 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.
}
}
Используйте
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.