1

我想创建一个异常层次结构。我使用了 C++ 成语“多态异常”。

困难的一点是我希望这些类从 std::exception 派生 - 能够使用 try ... catch(exception &e) 在代码的任何点捕获任何异常。

但是,无论异常来自 std::exception 还是来自我的用户定义的异常,我都想以不同的方式处理异常。

这建议使用多态性,但是我无法在 std::exception 上定义虚函数。

我也尝试过使用函数模板(参见下面的代码),但它不起作用,因为调用的模板函数是在编译时确定的。

#include <iostream>
#include <string>
using namespace std;

#include <boost\type_traits\is_base_of.hpp>
#include <boost\utility\enable_if.hpp>


class BaseError :public exception {
  public:
    virtual void raise(){throw *this;}
    virtual string msg (){ return "This is the base class"; }
  };

class DerivedError: public BaseError {
  public:
    void raise(){throw *this;}
    string msg (){ return "This is the derived class"; }
  };

template <typename T>
typename boost::disable_if<boost::is_base_of<BaseError, T>>::type
handleException(T &e)
{
    cout << "Handling generic exception" << endl;
    cout << e.what() << endl;
}
template <typename T>
typename boost::enable_if<boost::is_base_of<BaseError, T>>::type
handleException(T &e)
{
    cout << "Handling specific exception" << endl;
    cout << e.msg() << endl;
}


int main () {
  BaseError b;
  handleException(b);
  // prints "Handling specific exception"
  // prints "This is the base class"
  try{
      throw exception("Exception !!!");
  }
  catch (exception &e){
      handleException(e);
      // prints "Handling generic exception"
      // prints "Exception !!!"
  }
  try{
      BaseError b;
      b.raise();
  }
  catch (exception &e){
      handleException(e);
      // prints "Handling generic exception" - I would like the specific behaviour
      // prints "Unknown exception"
  }
  try{
      DerivedError d;
      d.raise();
  }
  catch (exception &e)
  {
      handleException(e);
      // prints "Handling generic exception" - I would like the specific behaviour
      // prints "Unknown exception"
  }
  return 0;
}

知道如何实现这一目标吗?

提前致谢!

4

1 回答 1

2

您可以在任何时候重新抛出异常,如果它发生在 catch 之间,它将被定义。例如:

try
{
    // something that throws an exception
} catch(std::exception& e) {
    try
    {
        throw; // rethrows the original exception
    } catch(std::runtime_error& e) {
        // handle runtime error
    } catch(std::exception& e) {
        // handle everything else
    }
}

现在嵌套try-catch块可以在任何地方,它可以是一个函数,甚至是一个对象析构函数。您可以组合一组处理特定异常的对象,将它们链接在一起并throw;在链的末端调用。伪代码:

template< typename E, typename Base = void >
struct exception_handler : Base
{
    void handle() const
    {
        try
        {
            Base::handle();
        } catch( E& e ) {
            // do something
        }
    }
};

template< typename E >
struct exception_handler< E, void >
{
    void handle() const
    {
        try
        {
            throw;
        } catch( E& e ) {
            // do something
        }
    }
};

那么上面的例子可以这样解释:

try
{
    // something that throws an exception
} catch(std::exception& e) {
    exception_handler<
        std::exception
      , exception_handler<
            std::runtime_error
        >
    > handler;
    handler.handle();
}

可以使用继承和常规类手动创建相同的层次结构,您可以在其中定义每个异常级别以及如何处理它们。

struct runtime_error_handler : base_handler
{
    void handle() const
    {
        try
        {
            throw;
        } catch( std::runtime_error& e ) {
            // if the original exception was a runtime_error it will be caught here
            // otherwise it will be propagated up the stack to exception_handler

            // do something if runtime_error
        }
    }
};

struct exception_handler : runtime_error_handler
{
    void handle() const
    {
        try
        {
            runtime_error_handler::handle();
        } catch(std::exception& e) {
            // do something else in the general case
        }
    }
};
于 2012-06-16T22:38:23.277 回答