std :: rethrow_exception和抛出的异常类型

Mik*_*hke 10 c++ c++11

在库中,我有一个例外(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::make_exception_ptr:

创建一个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)

  • @hvd ["异常对象在异常的最后剩余活动处理程序通过除了重新抛出之外的任何方式退出之后被破坏,或者是引用于std :: exception_ptr的类型的最后一个对象(\ [propagation \])异常对象被销毁,以较晚者为准."](http://eel.is/c++draft/except.throw#4) (4认同)
  • 此外,["引用的对象应至少在有引用它的`exception_ptr`对象时保持有效."](http://eel.is/c++draft/propagation#8). (2认同)