【问题标题】:Do the same action at the end of the try block and all catch clocks in a try-catch statement在 try 块的末尾和 try-catch 语句中的所有 catch 时钟执行相同的操作
【发布时间】:2015-12-06 15:37:54
【问题描述】:

这是一种避免代码重复的方法吗(FinalAction 函数在所有 catch 块和 try 块中调用)?

try
{
    // some actions including creation of new objects
    FinalAction();
}
catch (const Exception1& ex1)
{
    ProcessException1(ex1);
    FinalAction();
}
catch (const Exception2& ex2)
{
    ProcessException2(ex2);
    FinalAction();
}
// ...
catch (const ExceptionN& exN)
{
    ProcessExceptionN(exN);
    FinalAction();
}
catch (...)
{
    ProcessUnknownException();
    FinalAction();
}

更新: FinalAction() 应该在try 块中创建的对象的析构函数之前调用。像下面这样简单的解决方案在这里不起作用。

try
{
    // some actions including creation of new objects
}
catch (const Exception1& ex1)
{
    ProcessException1(ex1);
}
catch (const Exception2& ex2)
{
    ProcessException2(ex2);
}
// ...
catch (const ExceptionN& exN)
{
    ProcessExceptionN(exN);
}
catch (...)
{
    ProcessUnknownException();
}
FinalAction();

关于FinalAction 的更多信息:它不会抛出,也不会清理try 块中分配的任何资源。

【问题讨论】:

  • trycatch 调用相同的方法会提示代码异味。您能否向我们提供有关您要完成的工作的更多详细信息?也许这有助于找到解决方案。
  • FinalAction() 可能会抛出吗?如果不只是使用 RAII
  • @XavierÁlvarez 实际上这是一个简单的等待按键。但它给了我一个概括的想法。
  • @Mgetz 如何在这里使用 RAII?据我所知,将在第一个 catch 块之前调用 RAII 对象的析构函数。
  • @Puppy 那么在所有catch块之后就和它的简单调用一样。

标签: c++ c++11 try-catch c++14 code-duplication


【解决方案1】:

虽然您的问题并非完全重复,但this question 的答案是合适的。

您似乎要求的是相当于 C++ 中的 finally-clause,而答案是在 C++ 中这通常可以通过 RAII 解决。

我不会重复在链接的 SO 问题中给出的相当广泛的答案,但总而言之,您确保资源的清理是在析构函数中完成的。很可能您的FinalAction() 正在清理资源。

【讨论】:

  • 不,在我的问题中FinalAction 没有资源清理。
  • 即使是一个模糊的复制品,还有一百万英里的距离,“那个”答案?有七个!
  • @LightnessRacesinOrbit:已接受 的答案,即投票数是第二名的两倍多的答案,很好地描述了 RAII。在更新问题之前,不知道 FinalAction() 函数做了什么,“使用 RAII”在我看来是一个很好的答案。
  • @dhavenith:这是一个非常糟糕的答案。 OP 想了解如何使用 RAII 来达到最佳效果。只是“使用 RAII”是没有帮助的。
【解决方案2】:

我不知道 ProcessExceptionXFinalAction 属于哪些类,或者 ProcessException 是做什么的,但也许你可以只有一个ProcessException 获取一个参数并执行FinalAction,例如:

...
try {
  FinalAction();
}
catch (const Exception1& ex1) {
  ProcessException(ex1);
}
...

void ProcessException (Exception e) {
 // do things
 FinalAction();
}

【讨论】:

  • 不,我不能。 Exception1 ... ExceptionN 是不同的异常类,没有共同的基础。那么未知异常的处理呢?
【解决方案3】:

最简单的做法就是在try 块之后调用它。

bool success = false;
try
{
    // some actions including creation of new objects
    FinalAction();
    success = true;
}
catch (const Exception1& ex1)
{
    ProcessException1(ex1);
}
if (!success)
    FinalAction();

但是,这样做而不是使用类来管理您使用 FinalAction 清理的任何资源是非常可疑的。

【讨论】:

  • 感谢您的解决方案。不过有点丑不是吗?
  • 我不使用FinalAction 清理任何资源,这是一个简单的wait-for-a-keypress 操作。
  • @Constructor:直接表达你想要的语义——如果扔了,做FinalAction。
  • @Puppy 是的,我知道您的解决方案在这里很合适。我想以同样的方式做,但决定在Stack Overflow 搜索更好的解决方案。而且我还没有找到。
  • 真的没有更好的解决方案了。你需要编写代码来做你想做的事情。你无法解决这个问题。
猜你喜欢
  • 1970-01-01
  • 2016-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多