从std :: exception继承而无需更改用户代码

时间:2019-03-14 22:58:15

标签: c++ api-design

当前,在我们的API中,我们有自己的异常类型MyException,该类型不(既不直接也不间接)继承自std::exception或任何其他类型:

class MyException {
public:
    MyException(std::string const& message);
    std::string const& GetErrorMessage() const;
private:
    //...stuff, e.g. like the error-message.
};

给我们的客户(和我们自己的开发人员)带来了这样的负担:总是向尝试块添加至少两个catch-handler:

try {
    SomeLibraryFunction();
}
catch (MyException const& e) { std::cerr << e.GetErrorMessage(); }
catch (std::exception const& e) { std::cerr << e.what(); }

为减少catch-handler的数量,我想添加来自std::exception的继承。但是这样做的问题是它将“破坏”现有代码。即,编译器将选择与之前不同的catch-handler:

try {
    SomeOtherLibraryFunction();
}
catch(std::exception const& e) { std::cerr << "STD-EX"; }
catch(MyException const& e)
{
    std::cerr << "LIBRARY-EX";
    ExecuteMandatoryCodeWhenMyExceptionGetsThrown(e);
}

MyExceptionstd::exception继承后,第二个捕获处理程序将永远无法到达。原因here

  

当复合语句中的任何语句抛出类型E的异常时,它都会按照catch子句的列出顺序与handler-seq中每个catch子句的形式参数T的类型进行匹配。

有没有一种方法可以使编译器采用最佳匹配项而不是第一个匹配项?还是通过其他任何方式来实现从std::exception继承而无需更改将调用哪个catch-handler的方法?

1 个答案:

答案 0 :(得分:1)

最安全的方法是在这种情况下将异常类型更改为新的类型,例如MyExceptionV2,告诉人们它要好得多,MyException最终将被弃用。然后给他们一些时间来升级其捕获块以使用您的新类型并删除多余的捕获块。然后在下一版本中弃用它,然后在更高版本中删除MyException