使用std::logic_error代替返回false

6

我希望得到有关使用std::logic_error替代复杂的嵌套if/else if返回true/false的意见。

我想从下面这样很多类似函数中进行更改:

bool validate_data(){
    std::vector<int> v; 
    //fill with data
    if( v.find(10) == v.end() ){
       return false;
    } 
    // other checks that return false
}

to

bool validate_data(){
    std::vector<int> v; 
    //fill with data
    if( v.find(10) == v.end() ){
       throw std::logic_error("error message");
    } 
    // other checks that return false
}

在一个单独的try-catch块中调用所有这些函数列表。

由于它是从std::exception派生而来,我不知道这是否是一个好主意。

有人使用像下面的例子吗?

非常感谢

AFG


2
如果使用throw而不是return,你将拥有相同复杂的if/elseif代码。这样做有什么优势? - Tadeusz Kopec for Ukraine
@Tadeusz:由于所有内容都在单个验证失败中汇总,因此我可以编写更简单的代码,即在单个try/catch子句中调用这些验证函数的列表。 - Abruzzo Forte e Gentile
3个回答

5

只在特殊情况下使用异常。

不能找到值为10是一种特殊情况吗?还是说这只是一种普通情况?

将您的方法从validate_data重命名为is_data_valid会使其更清晰。如果该方法返回true,则有效,如果返回false,则无效。不需要使用异常来处理此问题。


1
std::logic_error的文档中写道:“该类作为所有异常的基类,用于报告在程序执行之前可能检测到的错误,例如违反逻辑前提条件”。这是否意味着我可以将其用作断言?这可能也会强制执行您所说的有效/无效与异常情况。 - Abruzzo Forte e Gentile
如果逻辑前提条件的违反意味着应用程序中存在错误,请使用assert。如果违反意味着用户提供了不正确的输入,请向用户报告错误。关于异常,我只会在您确定在应用程序中一致处理它时使用异常。这意味着您的所有方法都可以处理在执行过程中停止的情况。在我的情况下,我仍然有很多普通C代码,因此我不喜欢在我的应用程序中添加异常。 - Patrick

5
您应该仅在异常情况下使用异常。当其为真或假的几率较小时,使用(并检查)返回值更加有效。只有在抛出异常的机会非常小,超过了返回值检查的成本时,异常才更有效。
因此,如果无效数据的机会非常低,则使用异常。否则,当前解决方案不仅可以,而且稍微更有效(因为抛出和处理相对昂贵)。

1
嗨,Dennis!感谢您的回复(稍后才来)。在我经历了这些困境几次之后,我也会说除了必须使用“异常安全”技术外,没有其他例外。如果没有它,我发现我的程序是“不完整”的,而且并不真正安全。我现在使用boost scope exit 来解决这个问题。http://www.boost.org/doc/libs/1_52_0/libs/scope_exit/doc/html/index.html - Abruzzo Forte e Gentile

3

由于您的函数名为validate_data(),因此只有在函数内部出现任何内部错误时才会引发异常,并使用truefalse指示函数是否验证了输入,但它是validreturn true)或无效的(return false)。

这并不会阻止您拥有多个if() else if() else结构,但它会使代码更清晰,更易于区分数据是否无效或出现内部错误。

try {
  bool valid = validate_data(foo);
  /* process data or break if invalid */
} catch (std::exception &ex) {
  /* internal error happened */
}

正如你所看到的,它会让你的代码更长,但在我看来更加简洁。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接