方法的编码约定在C ++中返回

时间:2010-09-22 18:18:23

标签: c++ c naming-conventions conventions

我观察到成功完成方法预期功能的一般编码约定为0.(如exit(0)所示)。

这种让我感到困惑的原因是,如果我的if语句中的方法和方法返回0,则“if condition”为false,从而敦促我思考方法失败了一分钟。当然我知道我必须附加一个“!” (如if(!Method())),但这种惯例不是自相矛盾的吗?

8 个答案:

答案 0 :(得分:15)

您需要区分错误代码和错误标志。代码是表示任意数量错误的数字,而标志是表示成功的布尔值。

说到错误代码,我们的想法是:只有一种方法可以成功,但有许多方法可以失败。将0作为一个好的单一唯一编号,代表成功,然后你有其他所有数字是一种表示失败的方式。 (任何其他方式都没有意义。)

当谈到错误标志时,这个想法很简单:True表示它有效,false表示没有。您通常可以通过其他方式获取错误代码,并采取相应的行动。

某些功能使用错误代码,有些使用错误标记。没有什么令人困惑或倒退的事情,除非你试图将一切都视为旗帜。并非所有的返回值都是一个标志,这只是你必须习惯的东西。

请记住,在C ++中,您通常会处理异常错误。您只需从捕获的异常中获取必要的信息,而不是查找错误代码。

答案 1 :(得分:3)

这个惯例并不矛盾,它与你对函数的期望使用相矛盾。

其中一个必须改变,它不会成为惯例; - )

我通常会写:

if (Function() == 0) {
    // code for success
} else {
    // code for failure
}

if (Function() != 0)与案例相反。

整数可以隐式转换为布尔值,但这并不意味着你总是应该。 0此处表示0,并不代表false。如果你真的想,你可以写:

int error = Function();
if (!error) {
    // code for success
} else {
    // code for failure, perhaps using error value
}

答案 2 :(得分:0)

有各种约定,但C函数最常见的是失败时返回0,成功时返回正值,这样你就可以在if语句中使用它(几乎所有的CPU都有条件跳转,可以测试一个值是否为0这就是为什么在C中这个“被滥用”,0表示错误,其他一切都意味着真实。)

另一个惯例是在错误时返回-1,而在成功时返回其他一些值(尤其是使用POSIX函数设置errno变量时)。这就是0可以解释为“成功”的地方。

然后是exit。它是不同的,因为返回的值不是由C解释,而是由shell解释。在这里,值0表示成功,而其他每个值都表示错误条件(许多工具会告诉您此值发生了什么类型的错误)。这是因为在shell中,通常只有0-127的范围用于返回有意义的值(历史原因,它是无符号字节,127以上的所有内容都意味着被某些信号IIRC杀死)。

答案 3 :(得分:0)

您已将问题标记为[c] [c++]。这是什么?因为答案会有所不同。

你说:

  

我观察到成功完成方法预期功能的一般编码约定是0。

对于C,这很好。

对于C ++,它肯定是而不是 C ++有另一种发出失败信号的机制(即异常)。滥用(数字)返回值通常是设计不良的标志。

如果由于某些原因导致异常不通过,还有其他方法可以在不堵塞方法返回类型的情况下发出故障信号。替代方法包括返回bool(考虑方法try_insert)或使用无效/保留的返回值进行失败,例如string::npos方法使用的string::find发生在字符串中。

答案 4 :(得分:0)

exit(0)是一个非常特殊的情况,因为它是一个sentinel值,要求编译器告诉操作系统返回该操作系统上的实际成功值。它完全有可能不是数字0。

正如您所说,许多函数返回0表示成功,但它们主要是“遗留”C库OS接口函数,并且遵循首先开发和部署C的操作系统的接口样式。

在C ++中,0在包装这样的C遗留接口时可能是成功值。您可能考虑使用0表示成功的另一种情况是,当您有效地返回错误代码时,所有错误都是非零值,而0作为非错误值是有意义的。因此,不要将返回值视为布尔值(即使C ++会将其隐式转换为1),但作为错误代码,其中0表示“无错误”。 (实际上,使用枚举通常是最好的。)

但是,您通常应该从某些形式的谓词函数返回布尔值,例如is_empty(),has_dependencies(),can_fit()等,并且通常会在出错时抛出异常。在Alterantive中,根据libc的errno使用子系统(也许是线程)特定的错误代码值,或者接受一个单独的引用/指针参数来加载错误代码。

答案 5 :(得分:0)

int retCode = SaveWork();

if(retCode == 0) {
  //Success !
} else if(retCode == ERR_PERMISSIONS) {
  //User doesn't have permissions, inform him
  //and let him chose another place
} else if(retCode == ERR_NO_SPACE) {
  //No space left to save the work. Figure out something.
} else {
    //I give up, user is screwd.
}

因此,如果返回0 / false表示失败,则无法区分错误的原因。 对于C ++,您可以使用异常来区分不同的错误。你也可以用 一个全局变量,类似于errno,您可以在发生故障时进行检查。如果不需要异常或全局变量,则通常使用返回错误代码。

答案 6 :(得分:0)

正如其他答案已经说过的那样,使用0表示成功会使失败的一切都归零。通常(尽管不总是)这意味着使用单个非零值来指示失败的类型。正如已经说过的那样,在那种情况下,你必须将它视为错误代码而不是成功/失败标志。

在这种情况下,我绝对不愿意看到像if(!Method())这样的声明,这实际上是对成功的考验。对我自己而言,我发现它可能会让人想知道该陈述是否正在测试成功或失败。在我看来,因为它不是一个简单的布尔返回,所以它不应该像一个一样写。

理想情况下,由于返回被用作错误代码,该函数的作者应该提供可用于代替原始数字的枚举(或至少一组定义)。如果是这样,那么我总是希望将测试重写为像if(Method() == METHOD_SUCCESS)这样的东西。如果作者没有提供,但你有关于错误代码值的文档,那么考虑制作你自己的枚举或定义和使用它。

如果没有别的,我会把它写成if(Method() == 0),因为至少它应该仍然清楚读者方法不返回一个简单的布尔值,并且零具有特定的含义。


虽然经常使用该惯例,但它肯定不是唯一的惯例。我已经看到通过使用正值和负值来区分成功和失败的惯例。当一个函数在成功时返回一个计数,但是需要返回一个在失败时不是值计数的东西(通常为-1)时,会发生这种情况。我还看到使用无符号数的变体,其中(unsigned int)-1(又名0xffffffff)表示错误。还有其他一些我甚至无法想到的事情。

由于没有单一的正确方法,不同时期的不同作者都发明了各种方案。

当然,这完全没有提到异常提供(除其他外)在函数出错时提供信息的完全不同的方式。

答案 7 :(得分:0)

我在我的代码中使用此约定:

int r = Count();

if(r >= 0) {
   // Function successful, r contains a useful non-negative value
}
else {
   // A negative r represents an error code
}

我倾向于避免bool返回值,因为它们没有任何优点(甚至不考虑它们的大小,它被舍入到一个字节)并限制了函数返回值的可能扩展。

在使用例外之前,请考虑它们带来的性能和内存问题。