你能将一个异常继承层次结构包装成另一个吗? - 或者,另一个干净的方式处理这个?

Jam*_*ton 5 c++ stl

假设我有两个我在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)

可以理解的是,异常从未被捕获 - 它会从编译器中获得相当多的魔力来捕获它.

是否有一个解决方案可能类似于上面的包装遗留异常,并实现这些目标?

  • 一个"catch"子句或类似的,因此一般的异常处理逻辑只需要写一次.
  • 从一种异常类型转换为另一种异常类型的逻辑必须集中.
  • 如果可能,避免使用宏.
  • 没有使用lambda函数.

sya*_*yam 2

在使用 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 非常不标准,我不知道它是如何演变的,也许现在你可以做得更好。无论如何希望这会有所帮助。