从boost::exception和std::runtime_error继承自定义异常类

Inherit custom exception class from both boost::exception and std::runtime_error

本文关键字:error 继承 自定义异常 std boost exception runtime      更新时间:2023-10-16

我想介绍我的自定义异常类的层次结构,这些类从boost::exception和std::runtime_error派生而来,以便what()返回一些有意义的东西。

到目前为止,我运气不佳:

#include <iostream>
#include <stdexcept>
#include <boost/exception/all.hpp>
typedef boost::error_info<struct tag_foo_info, unsigned long> foo_info;
struct foo_error : virtual boost::exception, virtual std::runtime_error
{
  explicit foo_error(const char *const what)
    : std::runtime_error(what)
  { }
};
static void foo()
{
  BOOST_THROW_EXCEPTION(foo_error("foo error") << foo_info(100500));
}
int main(int argc, char *argv[])
{
  try
  {
    foo();
  }
  catch (const std::exception& e)
  {
    std::cerr << boost::diagnostic_information(e);
    return 1;
  }
  return 0;
}

只是不断抱怨CCD_ 3有CCD_。

我能得到的最接近的是使用抛出一个实际的std::runtime_error

BOOST_THROW_EXCEPTION(boost::enable_error_info(std::runtime_error("foo error")) << foo_info(100500)))

但那不是我真正想要的。基本上,我希望一个异常类是catch,可以由catch (const std::exception& e)catch (const std::runtime_error& e)catch (const boost::exception& e)catch (const foo_error& e)生成。这可能吗?提前谢谢。

您需要公共继承

struct Exception : public boost::exception, public std::runtime_error
{
    Exception()
    :   std::runtime_error("Hello World")
    {}
};
int main()
{
    try {
        try {
            throw Exception();
        }
        catch(const std::runtime_error&) {
            std::cout << "std::runtime_error" << std::endl;
            throw;
        }
    }
    catch(const boost::exception&) {
        std::cout << "boost::exceptionr" << std::endl;
    }
    return 0;
}

如果你替换两个虚拟的:,你的代码就会工作

Throw in function void foo()
Dynamic exception type: boost::exception_detail::clone_impl<foo_error>
std::exception::what: foo error
[tag_foo_info*] = 100500

boost异常库有一个派生自异常的类:

// Curiously recurring template pattern (exception.hpp:419:20)
class clone_impl: public Exception, public clone_base;

由于虚拟继承,大多数派生类负责初始化基类(clone_inmpl不初始化)

std::runtime_error已经从std::exception继承。因此,您只需要继承std::runtime_error,就可以同时获得这两个结果。

更新:我的意思是只继承std::runtime_error。如果你尝试这个:

#include <iostream>
#include <stdexcept>
struct foo_error : public std::runtime_error
{
    explicit foo_error(const char *const what)
        : std::runtime_error(what)
    { }
};
static void foo()
{
    throw foo_error("foo error");
}
int main(int argc, char *argv[])
{
    try
    {
        foo();
    }
    catch (const std::exception& e)
    {
        std::cerr << boost::diagnostic_information(e);
        return 1;
    }
    return 0;
}

为了简单起见,省略了boost的内容。