在库中,我有一个例外(RuntimeException -> RecognitionException -> NoViableAltException)的层次结构.在执行期间,NoViableAltException抛出一个,如下所示,并从中创建一个异常指针:
try {
//code that throws NoViableAltException
} catch (RecognitionException &re) {
std::exception_ptr e = std::make_exception_ptr(re);
reportError(e);
}
Run Code Online (Sandbox Code Playgroud)
e其他地方使用的值与此问题无关.在reportError()我实际处理错误:
void reportError(std::exception_ptr e) {
...
try {
std::rethrow_exception(e);
} catch (NoViableAltException &ne) {
reportNoViableAlternative(recognizer, ne);
} catch (InputMismatchException &ne) {
reportInputMismatch(recognizer, ne);
} catch (FailedPredicateException &ne) {
reportFailedPredicate(recognizer, ne);
} catch (RecognitionException &ne) {
recognizer->notifyErrorListeners(ne.getOffendingToken(), ne.what(), e);
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的问题:当我重新抛出时e,NoViableAltException分支不被采用,而是RecognitionException(最后一个).这是令人惊讶的,我想知道为什么会这样.我也试图抓住NoViableAltException*,但无济于事.捕获各个异常类型的正确方法是什么?
Ker*_* SB 14
不要用make_exception_ptr; 这是不同的东西(它使用推导的异常类型创建一个新的异常指针,并且您的代码最终会切割捕获的异常对象).相反,您想要捕获当前的异常:
catch (RecognitionException &)
{
std::exception_ptr e = std::current_exception();
// ...
}
Run Code Online (Sandbox Code Playgroud)
小智 8
创建一个std :: exception_ptr,它包含对e副本的引用.
不幸的是,复制 e意味着你得到了对象切片(@Mohamad Elghawi指出,该页面后面也会更加突出地提到).当你打电话时std::make_exception_ptr<RecognitionException>,它会保存一个RecognitionException,而不是任何派生类的副本.
但你根本不需要exception_ptr这里.即使在范围内reportError没有try... catch,您仍然可以使用throw;重新抛出当前异常.
#include <stdio.h>
struct A { virtual ~A() = default; };
struct B : A { };
void reportError() {
try {
throw;
}
catch (B &) {
puts("caught B");
}
catch (A &) {
puts("caught A");
}
}
int main() {
try {
throw B();
}
catch (A &) {
reportError();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1452 次 |
| 最近记录: |