使用嵌套的if语句来构造代码

时间:2013-09-30 11:20:43

标签: c++ c coding-style nested

我正在尝试以可读的方式构建我的代码。我读过这样做的一种方法如下:

if(Init1() == TRUE)
{
    if(Init2() == TRUE)
    {
        if(Init3() == TRUE)
        {
            ...
            Free3();
        }
        Free2();
    }
    Free1();
}

我喜欢这种做事方式,因为它将每个FreeX保持在匹配的InitX循环内,但如果嵌套超出三个级别,它很快就会变得不可读并超过80列。许多函数可以分解为多个函数,这样就不会发生这种情况,但为了避免过多的嵌套级别,分解函数似乎很愚蠢。特别是,考虑一个为整个类进行初始化的函数,其中初始化需要十个或更多函数调用。这是十层或更多层次的嵌套。

我确信我已经过度思考了这一点,但是上面有什么根本我缺失的东西吗?深度嵌套可以以可读的方式完成吗?或者以某种方式进行重组,同时将每个FreeX保留在自己的InitX循环中?

顺便说一句,我意识到上面的代码可以压缩到if(Init1() && Init2()...,但代码只是一个例子。每个InitX调用之间会有其他代码阻止这种压缩。

5 个答案:

答案 0 :(得分:4)

由于您包含了C ++标记,因此您应该使用RAII - 资源获取是初始化。有很多很好的在线资源可以解释这个概念,它将使很多与资源管理相关的事情变得更加容易。

答案 1 :(得分:2)

  

我确信我已经过度思考了这一点,但是上面有什么根本我缺失的东西吗? [...]或者以某种方式进行重组,同时将每个FreeX保留在自己的InitX循环中?

是。这是一个代码的教科书案例,将从RAII代码中获益匪浅:

而不是构造:

if(init(3) == TRUE)
{
    free3();
}

考虑一下:

raii_resource3 r3 = init3(); // throws exception if init3 fails
                             // free3 called internally
                             // by raii_resource3::~raii_resource3

您的完整代码变为:

raii_resource1 r1 = init1();
raii_resource2 r2 = init2();
raii_resource3 r3 = init3();

您将没有嵌套ifs,您的代码将清晰明了(并专注于积极的情况)。

您只需要为资源1,2和3编写RAII包装器。

答案 2 :(得分:2)

正如其他人所指出的,显而易见的答案是RAII。但如果 如果没有RAII,你就会出现过深的嵌套问题 应该问问自己,你是不是在做自己的职能 太复杂。函数应该很少超过约 十行(包括此类检查)。如果你看一下真实案例, 你会发现打破它几乎总是更有意义 功能。即使使用RAII,您通常也应该只有一个 每个函数的RAII类的实例。 (也有例外, 当然;可以说,std::lock_guard之类的东西不应该 数。)

答案 3 :(得分:0)

我建议使用switch语句。 当谈到像这样的代码时,我非常喜欢switch语句。

希望这有帮助。

switch (i) {
    case 1:
        // action 1
        break;
    case 2:
        // action 2
        break;
    case 3:
        // action 3
        break;
    default:
        // action 4
        break;
}

答案 4 :(得分:-1)

你可能听说过这是邪恶的,但如果你坚持使用c,那么使用gotos来处理这样的异常并不是“肮脏”:

foo()
{
  if (!Init1())
    goto Error1;
  if (!Init2())
    goto Error2;
  ...
  ...
Error2:
  Free2();
Error1:
  Free1();
}