简体   繁体   English

如何通过其运行时类型抛出异常?

[英]How to throw an exception by its run-time type?

I want to call a function that may throw an exception. 我想调用一个可能抛出异常的函数。 If it does throw an exception, I want to catch it and pass the exception object to a handler function. 如果它确实抛出异常,我想捕获它并将异常对象传递给处理函数。 The default implementation of the handler function is simply to throw the exception. 处理函数的默认实现只是抛出异常。 Here is whittled-down code to illustrate the issue: 以下是用于说明问题的削减代码:

struct base_exception : exception {
  char const* what() const throw() { return "base_exception"; }
};

struct derived_exception : base_exception {
  char const* what() const throw() { return "derived_exception"; }
};

void exception_handler( base_exception const &e ) {
  throw e; // always throws a base_exception object even if e is a derived_exception
}

int main() {
  try {
    throw derived_exception();
  }
  catch ( base_exception const &e ) {
    try {
      cout << e.what() << endl; // prints "derived_exception" as expected
      exception_handler( e );
    }
    catch ( base_exception const &e ) {
      cout << e.what() << endl; // prints "base_exception" due to object slicing
    }
  }
}

However, the throw e in exception_handler() throws a copy of the static type of the exception, ie, base_exception . 但是, exception_handler()throw e exception_handler()的静态类型的副本,即base_exception How can I make exception_handler() throw the actual exception having the correct run-time type of derived_exception ? 如何使exception_handler()抛出具有正确运行时类型的derived_exception实际异常? Or how can I redesign things to get what I want? 或者我如何重新设计东西以获得我想要的东西?

You can put a throw_me virtual function in the base exception class, and have every derived class override it. 您可以将throw_me虚函数放在基本异常类中,并让每个派生类覆盖它。 The derived classes can throw the proper most derived type, without slicing. 派生类可以抛出适当的派生类型,而不进行切片。 Even though the function has the same definition in each class, they're not the same - the type of *this is different in each case. 即使函数在每个类中具有相同的定义,它们也不相同 - *this的类型在每种情况下都不同。

struct base_exception : exception
{
  char const* what() const throw() { return "base_exception"; }
  virtual void throw_me() const { throw *this; }
};

struct derived_exception : base_exception
{
  char const* what() const throw() { return "derived_exception"; }
  virtual void throw_me() const { throw *this; }
};

void exception_handler( base_exception const &e ) {
  e.throw_me();
} 

You can use throw; 你可以使用throw; to re-throw the exception that was caught. 重新抛出被捕获的异常。 You could also use a template. 您也可以使用模板。

template<typename T> void rethrow(const T& t) { throw t; }

Throw by value, catch by reference . 按价值投掷,以参考方式捕获 It'll save you a lot of headaches. 它会为你省去很多麻烦。

What you are looking for is called "propagating" the exception. 您正在寻找的是被称为“传播”异常。 To do so, you have to use the throw keyword without parameters inside the catch block. 为此,您必须在catch块中使用不带参数的throw关键字。 It will not copy the exception and the exception will be caught by the next catch block on its way or will make your program abort if it's not caught again. 它不会复制异常,异常将被下一个catch块捕获,或者如果没有再次捕获,将使程序中止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM