如何避免使用多个if-else来检查返回值是否为错误代码?
How to avoid using multiple if-else to check whether the returned value is an error code?
我使用错误代码作为返回值。但是每次调用函数时,我都会使用 if-else 来检查返回值是否是一个好结果。 例如
int v1,v2,v3,v4;
v1 = func1();
if(v1 != OK){
// do somethings
}
else{
v2 = func2();
if(v2!=OK){
// do somethings
}
else{
v3 = func3();
if(v3!=OK){
// do somethings
}
else{
v4 = func4();
if(v4!=OK){
// do somethings
}
else{
.....
}
}
}
}
如果原型相同,则可以使用 loop:
using f_ptr = int (*)();
using error_f_ptr = void (*)();
std::pair<f_ptr, error_f_ptr> funcs[] = {
{&func1, &err1},
{&func2, &err2},
{&func3, &err3},
{&func4, &err4}
};
for (const auto& p : funcs) {
const int v = p.first();
if (v != OK) {
p.second();
return FAIL;
}
}
return OK;
您可以将代码包装到另一个函数中,以避免嵌套的 if-else 块。
void foo() {
int v = func1();
if (v != OK) {
// do somethings
return;
}
v = func2();
if (v != OK) {
// do somethings
return;
}
v = func3();
if (v != OK) {
// do somethings
return;
}
v = func4();
if (v != OK) {
// do somethings
return;
}
.....
}
以下是我在没有C++例外的情况下使用的一些模式。 在所有情况下,目的是在代码中具有单个返回点。 (因为单点回报通常会使代码更具可读性和可维护性 - 并非总是如此,但这是一件值得努力的好事。 此外,当您利用 RAII 时,所有解决方案都很棒(让局部变量的析构函数为您完成所有清理工作)。
经典方法是"三角形模式":
int MyCode()
{
int v1, v2, v3, v4;
int result = FAIL;
v1 = func1();
if (v1 == OK)
{
v2 = func2();
if (v2 == OK)
{
v3 = func3();
if (v3 == OK)
{
v4 = func4();
if (v4 == OK)
{
result = OK;
}
else
{
// handle func4 failure
}
}
else
{
// handle func3 failure
}
}
else
{
// handle func2 failure
}
else
{
// handle func1 failure
}
if (result != OK)
{
// general cleanup
}
}
对于上述情况,如果可以利用 RAII 或将大部分"句柄清理代码"放在末尾的// general cleanup
块中,则不必在每个嵌套的else
子句中编写冗余代码 - 可以完全排除 else 子句。
我喜欢使用的另一个变体是"链式成功检查":
int MyCode()
{
int result = OK;
result = func1();
if (result == OK)
{
// additional code to handle result of func1 before invoking func2
result = func2();
}
if (result == OK)
{
// additional code to handle result of func2 before invoking func3
result = func3();
}
else
{
// special error handling for func3 failing
}
if (result == OK)
{
result = func4();
}
if (result == OK)
{
// handle success case, if anything
}
else
{
// general error handling and function cleanup goes here
}
return result;
}
乍一看很奇怪,但是当您以上述样式编写代码时,它可以让您看到预期的代码流(当成功是常态时)。 您可能会注意到,当错误情况发生时,需要对result==OK
进行大量冗余检查。在发布版本中,编译器可以对此进行优化。
链式成功检查的另一种变体是使用...等着吧...不要惊慌失措...一个 goto 宏,专门用于在失败时跳到函数的末尾(人群喘息)。 但是看看它使代码看起来多么简单:
#define JUMP_ON_ERROR(expr) {result = (expr); if (result != OK) goto Cleanup;}
int MyCode()
{
int result = OK;
JUMP_ON_ERROR(func1());
JUMP_ON_ERROR(func2());
JUMP_ON_ERROR(func3());
JUMP_ON_ERROR(func4());
Cleanup:
if (result == OK)
{
// handle success
}
else
{
// handle failure
}
return result;
}
考虑使用 try catch 块并在函数中抛出异常,而不是返回错误值
int v1, v2, v3, v4;
try
{
v1 = func1();
v2 = func2();
v3 = func3();
v4 = func4();
}
catch (Func1Exception e)
{
//handle Func1Exception
}
catch (Func2Exception e)
{
//handle Func2Exception
}
catch (Func3Exception e)
{
//handle Func3Exception
}
catch (Func4Exception e)
{
//handle Func4Exception
}
看到这个和这个
相关文章:
- 从python中调用C++函数并获取返回值
- 为什么模板类中的对象不能返回值
- 返回值优化:显式移动还是隐式
- lock_guard是否保护返回值
- 调用CreateProcess()并获取字符串的返回值
- 如何使 windows 命令提示符在C++可执行文件上显示返回值?
- 编译器警告:执行到达值返回函数的末尾而不返回值
- 查找 GCD:并非所有控制路径都返回值
- 在 Arduino 上使用 sscanf 会导致与 const char * 不匹配,并且返回值始终相同,尽管输入值不同
- 将返回值存储在函数指针数组的指针中是如何工作的?
- 如何从 std::thread 返回值
- 检查 std::string.c_str() 的返回值
- 如何获取有关 Visual Studio 代码分析中未经检查的函数返回值的警告
- 优化的范围检查并返回值
- 如何避免使用多个if-else来检查返回值是否为错误代码?
- 有必要用C++检查发送0MQ的返回值吗
- 如何检查忍者并行构建的返回值
- 是否有任何 ATL 支持的宏可以检查 hResults 并返回值
- 在 C++ 中传递 int 变量 - 错误检查不返回值
- 检查返回值是整数还是字符