定义异常类

Defining exception classes

本文关键字:异常 定义      更新时间:2023-10-16

我想知道为给定程序定义自己的异常类是否通常是一种很好的做法。例如,我有一个程序,主要读取/写入文件,并修改iptables规则。我也为程序编写了自己的基本记录器类。为了处理意外的值或错误(例如打开文件),我通常使用std::runtime_error.我想知道定义我自己的异常类通常是否是一个好主意。例:

void Protocol::set_port(const unsigned long &port) {
if ( (port > 0) && (port < 65535) ) {
port_ = port;
}
else {
throw std::invalid_argument("Invalid port number");
}
}

我不喜欢使用一大堆尝试和捕捉块,因为我发现这是一种糟糕而丑陋的做法(尽管我可能是错的)。

我想知道为给定程序定义自己的异常类通常是否是一种很好的做法。

是的,通常异常的类型应该是源或原因的描述,因此您可以通过模式匹配而不是代码来处理该特定异常。

我通常使用std::runtime_error。我想知道定义我自己的异常类通常是否是一个好主意。

是的,一般来说,您应该遵循以下规则:

  1. 显然,仅使用异常来报告异常故障(即不满足前提条件,或由于程序不正确操作之外的原因而不可用的资源)。

  2. 如果失败是逻辑错误(调用方试图在程序域中执行非法操作),则从std::logic_error中派生异常。

  3. 如果失败是无效参数的结果,那么从std::invalid_argument派生是有意义的。

  4. 如果失败是运行时错误(例如文件丢失),则派生自std::runtime_error.

    嵌套异常也很有用,因为您可以传递异常的摘要和原因以供以后诊断,例如:

 

struct port_out_of_range : std::invalid_argument
{
port_out_of_range(std::string const& context, unsigned long given)
: std::invalid_argument(context + ": port given: " + std::to_string(given))
{
}
};
void Protocol::set_port(const unsigned long &port) 
{
if ( port < 65535 ) {
port_ = port;
}
else {
throw port_out_of_range("Protocol::set_port", port);
}
}

。后。。。

try {
// ... some things ...
foo.set_port(x);
// ... more things ...
}
catch(port_out_of_range& e)
{
// maybe some remedial action possible here
}
catch(std::exception& e)
{
// but not here
log(e);
throw;
}