假设我有两个我在C++中处理的继承层次结构.一个继承自std::exception(新层次结构),另一个继承自Exception(旧版C++ Builder VCL基本异常类).如果我调用可能抛出任何类型异常的代码,我必须编写如下代码:
try {
// do stuff....
Function1();
Function2();
} catch (std::exception &ex) {
std::cout << "STL exception caught: " << ex.what() << std::endl;
} catch (Exception &ex) {
std::cout << "Legacy exception caught: " << ex.Message.c_str() << std::endl;
} catch (SomeOtherVendorLibraryException &ex) {
// etc.
}
Run Code Online (Sandbox Code Playgroud)
问题是每个调用者都需要拥有所有这些catch子句来尝试获取每个最后一种类型的异常,因为C++没有一个真正的,强制执行的异常基类,你可以将它作为一个全能System.Exception类(例如C#中的类).(catch (...)因为你没有办法知道你抓到了什么,所以是一个非启动者,并且可能会捕获一些危险的系统异常,例如访问冲突,最好不要使用它们.)
我想将这些"遗留"异常包装到std::exception层次结构中的类中.将第三方异常包装到您自己的异常系统中的概念并非完全前所未有.例如,.NET Framework在其他系统中包含大量错误(例如COMException).理想情况下,我希望看到这样的事情:
class LegacyException : public std::runtime_error {
public:
// construct STL exception from legacy exception
LegacyException(const Exception &ex) : std::runtime_error(ex.Message.c_str()) {}
};
try {
// In reality, this throw will happen in some function we have no control over.
throw Exception("Throwing legacy exception!");
} catch (std::exception &ex) {
// Ideally, the compiler would use the LegacyException constructor
// to cast the thrown Exception to a LegacyException, which ultimately
// inherits from std::exception.
std::cout << ex.what() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
可以理解的是,异常从未被捕获 - 它会从编译器中获得相当多的魔力来捕获它.
是否有一个解决方案可能类似于上面的包装遗留异常,并实现这些目标?
在使用 BC++Builder 后,我遇到了同样的问题,宏似乎是当时唯一的解决方案。
“更干净”(嗯......)解决方案可能是一种“双重 try-catch”:内部 try-catch 将遗留异常转换为标准类,而外部实际处理异常。
我手头没有代码(已经好几年了),但基本上可以归结为:
#define DTRY try { try
#define DCATCH catch (Exception& e) { throw LegacyException(e); } } catch
DTRY {
...
}
DCATCH(std::exception& e) {
// handle the exception
}
Run Code Online (Sandbox Code Playgroud)
是的,我知道它很难看,但是当我与 Borland 合作时,我没有发现更好的东西。事实是,当时 Borland 非常不标准,我不知道它是如何演变的,也许现在你可以做得更好。无论如何希望这会有所帮助。