我正在编写一些会抛出自定义异常的新代码 - 我想要包含错误字符串和状态代码。哪个类应该是异常派生的? std::exception
? std::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);
答案 0 :(得分:8)
Boost在error and exception处理方面有一篇很好的文档,讨论了常见问题以及如何从std :: exception(s)正确继承。
答案 1 :(得分:6)
考虑状态代码是否真的合适。它通常优于创建异常类的层次结构。这样,调用者可以更好地控制要处理的异常以及如何使界面更简单。
当然,有时候状态代码仍然合适(编译器会一直使用它们)。
答案 2 :(得分:3)
您可以使用任何标准异常类型作为基础,但如果您选择正确的类型,它将真正帮助该类用户(包括您自己):
当然,如果能更好地描述错误,您还可以使用其他标准派生异常之一(例如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
}