c/c++语言开发共享模式避免“如果清理失败”重复

我有一些看起来像这样的代码:

int myfunc() { blah a; blah2 b; blah3 c; blah4 d; blah5 e; int iRes = DoSomething1(a, b, c); if (iRes > 0) { clean1(a, b, c); clean2(d, e); log_error(); return 1; } iRes = DoSomething2(a, c, e); if (iRes > 0) { clean1(a, b, c); clean2(d, e); log_error(); return 1; } ... iRes = DoSomething10(c, d, e); if (iRes > 0) { clean1(a, b, c); clean2(d, e); log_error(); return 1; } clean1(a, b, c); clean2(d, e); return 0; } 

如何在C或C ++中避免重复if (iRes > 0) { clean1(a, b, c); clean2(d, e); log_error(); return 1; } if (iRes > 0) { clean1(a, b, c); clean2(d, e); log_error(); return 1; } 每个函数调用后?


笔记:

例:

这段代码是这种情况的一个例子:每10行代码实际上= 2行仅用于实际执行 + 8行错误测试和清理……我们能做得更好吗?

    正如贾斯汀所说,答案将根据语言的不同而有所不同。

    如果你在C,这是goto在语言中有一个据点的最后一个地方。 例如,如果您有:

     int myfunc() { blah a; blah2 b; blah3 c; blah4 d; blah5 e; int iRes = DoSomething1(a, b, c); if (iRes > 0) { goto error_cleanup; } iRes = DoSomething2(a, c, e); if (iRes > 0) { goto error_cleanup; } /*...*/ iRes = DoSomething10(c, d, e); if (iRes > 0) { goto error_cleanup; } /* SUCCESS */ clean1(a, b, c); clean2(d, e); return 0; /* ERROR EXIT POINT */ error_cleanup: clean1(a, b, c); clean2(d, e); log_error(); return 1; } 

    但是,在C ++中,我们需要处理这个清理代码,即使抛出exception,这也会使事情变得更加棘手。 但是,在c ++中我们也有RAII,这意味着析构函数是可行的方法。

    这是我喜欢的一个技巧,避免了goto:

     bool success = false; do { r = do_something(); if (r) break; r = do_something_else(); if (r) break; r = do_something_again(); if (r) break; success = true; } while(0); if (! success) { clean_up(); } 

    对于给定的代码,您可以使用以下任何一种变体:

     int myfunc() { blah a; blah2 b; blah3 c; blah4 d; blah5 e; int iRes; if ((iRes = DoSomething1(a, b, c)) > 0 || (iRes = DoSomething2(a, c, e)) > 0 || ... (iRes = DoSomething10(c, d, e)) > 0) { clean1(a, b, c); clean2(d, e); log_error(); return 1; } clean1(a, b, c); clean2(d, e); return 0; } 

    如果在clean1()clean2()之前或之后clean1() clean2() ,可以使用:

     int myfunc() { blah a; blah2 b; blah3 c; blah4 d; blah5 e; int iRes; if ((iRes = DoSomething1(a, b, c)) > 0 || (iRes = DoSomething2(a, c, e)) > 0 || ... (iRes = DoSomething10(c, d, e)) > 0) { log_error(); } clean1(a, b, c); clean2(d, e); return 0; } 

    甚至:

     int myfunc() { blah a; blah2 b; blah3 c; blah4 d; blah5 e; int iRes; if ((iRes = DoSomething1(a, b, c)) > 0 || (iRes = DoSomething2(a, c, e)) > 0 || ... (iRes = DoSomething10(c, d, e)) > 0) { // Don't need to do anything here } clean1(a, b, c); clean2(d, e); if (iRes > 0) log_error(); return 0; } 

    if的主体可能是最终的任务:

     int myfunc() { blah a; blah2 b; blah3 c; blah4 d; blah5 e; int iRes; if ((iRes = DoSomething1(a, b, c)) > 0 || (iRes = DoSomething2(a, c, e)) > 0 || ... ) { iRes = DoSomething10(c, d, e); } clean1(a, b, c); clean2(d, e); if (iRes > 0) log_error(); return 0; } 

    这种重构取决于清理在所有情况下都是相同的。 通常,它不是那么系统化。 由于您没有显示abcde中的任何a被初始化,因此很难确定什么是真正安全的。 如果doSomethingN()函数在C ++中并通过引用获取参数,则doSomething1()可以初始化abc – 但是在de具有值之前可能会发生对clean2()的调用。

      以上就是c/c++开发分享模式避免“如果清理失败”重复相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/550074.html

      (0)
      上一篇 2021年1月14日
      下一篇 2021年1月14日

      精彩推荐