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

时间:2011-03-24 14:42:33

标签: c++ exception-handling

我想调用一个可能抛出异常的函数。如果它确实抛出异常,我想捕获它并将异常对象传递给处理函数。处理函数的默认实现只是抛出异常。以下是用于说明问题的简化代码:

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
    }
  }
}

但是,throw e中的exception_handler()会抛出异常的静态类型的副本,即base_exception。如何使exception_handler()抛出具有正确运行时类型derived_exception实际异常?或者我如何重新设计东西以获得我想要的东西?

4 个答案:

答案 0 :(得分:3)

您可以在基本异常类中放置一个throw_me虚函数,并让每个派生类都覆盖它。派生类可以抛出适当的派生类型,而不进行切片。即使函数在每个类中具有相同的定义,它们也不相同 - *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();
} 

答案 1 :(得分:2)

您可以使用throw;重新抛出已捕获的异常。您也可以使用模板。

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

答案 2 :(得分:0)

Throw by value, catch by reference。它会为你省去很多麻烦。

答案 3 :(得分:-1)

您正在寻找的内容称为“传播”异常。为此,您必须使用throw块中没有参数的catch关键字。它不会复制异常,并且异常将在下一个catch块中被捕获,或者如果它没有被捕获则会使程序中止。