我应该抛出什么类型的例外?

sta*_*tor 19 c++ exception-handling

通过对异常处理的一些链接去后(1,2,和3),我知道C++程序可以引发相当多的东西异常(int,char*,string,exception类).我知道这std::exception是程序抛出的标准异常的基类.但是,我正在尝试设计一个try... catch块这样:

try
{
    MyFunc();
}
catch (certain exceptions)
{
    // deal with the exception accordingly
}
catch (the rest of the exceptions)
{
    // deal with these accordingly
}
Run Code Online (Sandbox Code Playgroud)

同时MyFunc()包含以下内容:

void MyFunc()
{
    ...
    if (certain condition is true) throw exception;
    ...
}
Run Code Online (Sandbox Code Playgroud)

麻烦的是,在MyFunc函数的那一部分,我不确定应该抛出什么类型的异常.为了通过实现我自己的异常类来保持代码清洁,我不知道什么是实现这样的异常类的好方法.

Dan*_*ker 19

您可以从中派生自己的类std::exception,以便有一些统一处理异常的方法.

如果这看起来有点过分,您可以抛出std::logic_error或者使用其他一些标准异常类型供应用程序使用.

您也可以将这些作为基类用于您自己的更具体的异常:这样可以省去一些工作,因为它们会what为您实现该方法.

请注意,深层异常层次结构可能无法使用,因为您基本上会提前猜测如何对错误进行分类,并且您的客户可能不同意.


Vij*_*hew 12

这是一个代码片段,展示了如何扩展和使用std :: exception类:(顺便说一下,这段代码有一个bug,我稍后会解释).

#include <iostream>
#include <string>
#include <exception>

class my_exception : public std::exception
{
public:
   explicit my_exception(const std::string& msg)
      : msg_(msg)
   {}

   virtual ~my_exception() throw() {}

   virtual const char* what() const throw()
   {
      return msg_.c_str();
   }

private:
   std::string msg_;
};

void my_func() throw (my_exception&)
{
  throw my_exception("aaarrrgggg...");
}

int
main()
{
  try
    {
      my_func();
    }
  catch (my_exception& ex)
    {
      std::cout << ex.what() << '\n';
    }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

请注意,构造函数是显式的,并且声明了析构函数和what()(使用throw())以指示它们自己不会抛出异常.这就是bug的地方.是否保证对msg_.c_str()的调用不会抛出自己的异常?我们用来初始化msg_的字符串构造函数怎么样?它也可以引发异常.我们如何设计一个对成员对象引发的异常安全的异常类?答案是 - 继承自std :: runtime_error或类似的std :: exception子类.因此,实现my_exception的正确方法是:

class my_exception : public std::runtime_error
{
public:
    my_exception(const std::string& msg) 
        : std::runtime_error(msg)
    { }
};
Run Code Online (Sandbox Code Playgroud)

我们不需要覆盖what(),因为它已经在std :: runtime_error中实现了.正确处理消息缓冲区是由std :: runtime_error完成的,因此我们可以确定my_exception本身不会在运行时抛出一些未知错误.