假设我有两个在 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.
}
问题是每个调用者都需要拥有所有这些 catch 子句来尝试获取最后一种类型的异常,因为 C++ 没有一个真正的、强制的异常基类,您可以将其用作包罗万象的System.Exception
类(例如 C# 中的类)。(catch (...)
这是一个非首发,因为你没有办法知道你捕获了什么,并且一些危险的系统异常,如访问冲突,也可能被捕获,最好不要陷入困境。)
我想将这些“遗留”异常包装到std::exception
层次结构中的一个类中。这种将第 3 方异常包装到您自己的异常系统中的概念并非完全没有先例。例如,.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;
}
可以理解的是,异常永远不会被捕获——它会要求编译器使用相当多的魔法来捕获它。
是否有可能与上述类似的解决方案来包装遗留异常并实现这些目标?
- 一个“catch”子句或类似子句,因此一般异常处理逻辑只需要编写一次。
- 从一种异常类型转换为另一种异常类型的逻辑必须集中。
- 尽可能避免使用宏。
- 不使用 lambda 函数。