滚动我自己的例外

时间:2008-12-03 08:13:05

标签: c++ exception

我正在编写一些会抛出自定义异常的新代码 - 我想要包含错误字符串和状态代码。哪个类应该是异常派生的? std::exceptionstd::runtime_error?还有其他'陷阱'需要担心吗?我正在考虑以下内容:

class MyException : public std::exception(?)
{
public:
    enum Status
    {
        ERROR_FOO,
        ERROR_BAR,
        ...
    };

    MyException(const std::string& error, Status code) :
        error_(error), code_(code)
    {
        ...
    }

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

    Status code() const
    {
        return code_;
    }
private:
    std::string error_;
    Status code_;
};

然后在代码中:

throw MyException("Ooops!", MyException::ERROR_BAR);

6 个答案:

答案 0 :(得分:8)

Boost在error and exception处理方面有一篇很好的文档,讨论了常见问题以及如何从std :: exception(s)正确继承。

答案 1 :(得分:6)

考虑状态代码是否真的合适。它通常优于创建异常类的层次结构。这样,调用者可以更好地控制要处理的异常以及如何使界面更简单。

当然,有时候状态代码仍然合适(编译器会一直使用它们)。

答案 2 :(得分:3)

您可以使用任何标准异常类型作为基础,但如果您选择正确的类型,它将真正帮助该类用户(包括您自己):

  • 如果错误是可以避免的,如果用户更加小心或精确,那么请使用 logic_error
  • 如果是来自系统的用户无法阻止的内容,请使用 runtime_error

当然,如果能更好地描述错误,您还可以使用其他标准派生异常之一(例如invalid_argument, range_error, bad_cast)。

答案 3 :(得分:2)

您的异常类不是异常安全的。如果std :: string的复制构造函数抛出异常,程序将被终止。

class MyException : public std::exception
{
public:
    enum Status
    {
        ERROR_FOO,
        ERROR_BAR,
        ...
    };

    MyException(const char* error, Status code) :
        std::exception(error),
        code_(code)
    {
        ...
    }
    ...
private:
    Status code_;
};

答案 4 :(得分:1)

在这方面非常有用的资源是Marshall Cline的C++ FAQ LITE。他有一章exceptions and error handling可能对你有用。

答案 5 :(得分:0)

析构函数和what()方法都应该标记为no throw 在MS-Studio中它忽略了throw限定符并且编译得很好,但为了符合标准和可移植性,你应该将它添加到你的代码中。

// What is a no throw operation.
virtual const char* what() const throw ()
{
    return error_.c_str();
}

其他评论:

我不会直接从例外继承 查看从异常派生的标准异常,看看是否符合该法案。

而不是使用错误代码。您可以使用异常类型的层次结构。这使得它更容易捕获。

class MyException: public std::runtime_error
{  // STUFF  .. Put all the error message stuff here
};

class MyFOO_Exception: public MyException
{  // STUFF
};

class MyBAR_Exception: public MyException
{  // STUFF
}