【问题标题】:How to cast boost::exception?如何施放 boost::exception?
【发布时间】:2017-10-30 02:25:20
【问题描述】:

考虑以下示例(取自https://theboostcpplibraries.com/boost.exception

#include <boost/exception/all.hpp>
#include <exception>
#include <new>
#include <string>
#include <algorithm>
#include <limits>
#include <iostream>

typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info;

struct allocation_failed : public std::exception
{
  const char *what() const noexcept { return "allocation failed"; }
};

char *allocate_memory(std::size_t size)
{
  char *c = new (std::nothrow) char[size];
  if (!c)
    BOOST_THROW_EXCEPTION(allocation_failed{});
  return c;
}

char *write_lots_of_zeros()
{
  try
  {
    char *c = allocate_memory(std::numeric_limits<std::size_t>::max());
    std::fill_n(c, std::numeric_limits<std::size_t>::max(), 0);
    return c;
  }
  catch (boost::exception &e)
  {
    e << errmsg_info{"writing lots of zeros failed"};
    throw;
  }
}

int main()
{
  try
  {
    char *c = write_lots_of_zeros();
    delete[] c;
  }
  catch (boost::exception &e)
  {
    std::cerr << *boost::get_error_info<errmsg_info>(e);
  }
}

函数allocate_memory()使用以下语句抛出异常

BOOST_THROW_EXCEPTION(allocation_failed{});

如何在 catch 块中将 boost::exception &amp;e 转换回 allocation_failed

另外,如果我的代码有多个 throw 语句,例如 BOOST_THROW_EXCEPTION(A{})BOOST_THROW_EXCEPTION(B{})BOOST_THROW_EXCEPTION(C{}) 等。其中 A、B、C 是类。在不使用 boost 的情况下,我可以通过以下方式为每种类型的异常设置单独的 catch 块。

...
catch(A e){
...
}
catch(B e){
...
}
catch(C e){
...
}

如何在使用 boost 时做同样的事情,让 BOOST_THROW_EXCEPTION(A{})BOOST_THROW_EXCEPTION(B{})BOOST_THROW_EXCEPTION(C{}) 等进入不同的 catch 块?

我是 boost 库的新手,它的一些概念让我难以理解。

【问题讨论】:

  • 为什么要坚持boost? (为什么不使用 RAII?)
  • 我正在使用以这种方式引发异常的 API。我将不得不阅读有关 RAII 的信息。过关后会回来的。谢谢。

标签: c++ boost exception-handling


【解决方案1】:

BOOST_THROW_EXCEPTION 除了继承boost::exception 之外,总是抛出一个继承其参数类型的类型。这意味着两件事:

  1. 您可以将dynamic_castboost::exception 转换为所传递的类型。

-

catch (boost::exception &e)
{
    std::cerr << *boost::get_error_info<errmsg_info>(e);
    if ( allocation_failed* af = dynamic_cast<allocation_failed*>(&e) )
    {
        std::cerr << af->what() << std::endl; // redundant
    }
}
  1. 您可以直接捕获传递的类型。但是,您应该始终通过引用来捕获以避免切片。 (此建议与您使用的是 boost 还是其他无关。)

-

catch (A& a) {
    // ...
} catch (B& b) {
    // ...
} catch (C& c) {
    // ...
}

当然,这样做,如果你想要任何 boost 的错误格式或额外的数据,你需要然后将 dynamic_cast 异常对象 boost::exception*

【讨论】:

  • 澄清一下——BOOST_THROW_EXCEPTION() 抛出的异常类型继承自参数类型和 boost::exception。这意味着在 BOOST_THROW_EXCEPTION(A{}) 中,抛出的类型继承自 boost::exception 和 A,而类型 A 本身不需要继承自 boost::exception。我的理解正确吗?
  • 没错。 (或者如果A 确实继承了boost::exception,它不会“添加另一个”。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-03
相关资源
最近更新 更多