我有一个engine.dll模块,它实现了几个处理功能,我创建了一个PublicInterface.h
,定义了外部访问的功能,
namespace PublicInterface {
void do_a();
void do_b();
}
我想保证PublicInterface
中对函数的每次调用都受try catch块的保护。换句话说,我希望engine.dll
处理它抛出的所有异常。实现这一目标的最佳方式是什么?
我想过创建一个额外的功能,
void protectedRun(std::function<void()> f) {
try {
f();
}
catch (...) {
_handle();
}
但是,如何强制PublicInterface.h
调用protectedRun()
中的所有功能?
或者有更好的方法来实现这个吗?
答案 0 :(得分:1)
解决方案取决于您想要实现的目标:
如果您希望用户处理代码中的所有可能异常,则没有直接方法强制他们使用protectedRun
调用函数。 C ++没有相应的Java检查异常。
如果要确保代码中没有异常传播到调用者的代码,您可以添加一个新的公共接口来处理所有异常,并(可选)使您当前的公共接口变为私有。
简而言之,用户可以访问代码中的异常(可能不会处理它们),或者他不会(并且没有任何处理它们的选项)。
答案 1 :(得分:1)
按如下方式实施:
using exceptionHandler = void(*)(std::exception& e);
void defaultHandler(std::exception& e) { throw e; }
namespace PublicInterface {
void do_a(exceptionHandler eh = &defaultHandler);
void do_b(exceptionHandler eh = &defaultHandler);
}
在你的功能中,不要直接投掷,而是将例外传递给(*eh)()
。
答案 2 :(得分:1)
唯一真正的方法是不将函数抛出到公共接口中。相反,将protectedRun()函数放在公共接口中,让它调用您的抛出函数,捕获这些异常,并(最重要的是)纠正导致抛出异常的问题。
然而,从根本上说,事实上你有抛出异常的函数并且试图强制它们被捕获的方式表明你的库有一个严重的设计缺陷。
异常的全部内容是报告错误情况的机制:(a)在检测到条件的情况下无法纠正;(b)必须先纠正条件,否则可能发生其他任何事情(程序终止除外)。 / p>
试图指示调用者必须立即捕获异常并纠正原因是没有意义的。如果调用者无法纠正原因,但无论如何都被迫以某种方式捕获它,唯一可用的选择是重新抛出异常。除了捕获和重新抛出的额外运行时开销之外,它具有相同的效果(堆栈展开),就好像调用者根本不捕获异常一样。
你需要做的是仔细考虑是否适合你的库中的函数来抛出异常。因为库函数的调用者不负责捕获异常。库函数负责以对调用者有意义的方式抛出异常。
还有一个基本问题,根据您的工具链(编译器,链接器等用于构建DLL与用于构建调用程序的那些)和环境(主机系统等)异常可能无法干净地跨越DLL边界无论如何。