如何正确实施最终条件?

时间:2010-07-16 08:29:21

标签: c++

这就是我要做的事情(这是对真实项目的简化):

int param;
int result;
void isolated(int p) {
  param = p;
  try {
    // make calculations with "param" and place the
    // result into "result"
    process();
  } catch (...) {
    throw "problems..";
  }
}

我无法改变process()的工作方式,因为此功能不是在项目中创建的,而是第三方功能。它适用于全局变量paramresult,我们无法改变它。

isolated()使用其他参数调用process()时,会出现问题。我想抓住这种情况,但不知道该怎么做,因为在C ++中没有finally。我觉得我应该使用RAII技术,但在这种情况下无法弄清楚如何正确地做到这一点。

我可以通过代码复制实现这一目标:

int param;
int result;
void isolated(int p) {
  static bool running;
  if (running) {
    throw "you can't call isolated() from itself!";
  }
  running = true;
  param = p;
  try {
    // make calculations with "param" and place the
    // result into "result"
    process();
    running = false;
  } catch (...) {
    running = false; // duplication!
    throw "problems..";
  }
}

5 个答案:

答案 0 :(得分:5)

“finally”喜欢在C ++中使用保护对象处理情境,这些对象最终在析构函数中执行。这是IMHO更强大的方法,因为您必须分析情况以最终确定以创建可重用的对象。在这种情况下,我们需要使进程租用,因为参数和返回在全局变量中传递。解决方案是在输入时保存它们的值并在退出时恢复它们:

template<class T>
class restorer 
{
 T &var; // this is the variable we want to save/restore
 T old_value; // the old value
 restorer(const restorer&); 
 void operator=(const restorer&); 
 public:
 restorer(T &v) : var(v), old_value(v) {}
 ~restorer() { var=old_value; }
};

int param;
int result;
int isolated(int p) {
  restorer<int> rest_param(param);
  restorer<int> rest_result(result);

  param = p;
  try {
    // make calculations with "param" and place the
    // result into "result"
    process();
    return result;
  } catch (...) {
    return 0;
  }
}

答案 1 :(得分:2)

也许我没弄错,但你为什么不用旗?你想知道何时从process()调用isolated(),对吧?

int isolated(int p) {
    static int execDeep = 0;
    execDeep++;

    // your code here

    execDeep--; 
}

现在您可以检查'execDeep'值,&gt; 1表示在执行过程中从进程()调用它。

答案 2 :(得分:1)

我仍然不太确定finally在这里是如何相关的,但如果您想避免自己创建范围保护结构,可以尝试Boost.ScopeExit

示例:

#include <boost/scope_exit.hpp>
#include <cstdio>

int isolated(int p) {
    static bool running = false;
    if (running) {
        printf("Throwing %d\n", p);
        throw p;
    }
    printf("Starting %d\n", p);
    running = true;
    BOOST_SCOPE_EXIT( (p)(&running) ) {   // <--
        printf("Stopping %d\n", p);       // <--
        running = false;                  // <--
    } BOOST_SCOPE_EXIT_END                // <--

    // ...
    if (p)
        isolated(p*10);
    // ...
    printf("Returing %d\n", p);

    return 4;
}

int main() {
    printf(">> first\n");
    isolated(0);
    printf(">> second\n");
    try {
        isolated(1);
        printf(">> third (should not be printed.)\n");  
    } catch(int p) {
        printf("Caught %d\n", p);
    }
    isolated(0);
    printf(">> fourth\n");

    return 0;
}

结果:

>> first
Starting 0
Returing 0
Stopping 0
>> second
Starting 1
Throwing 10
Stopping 1
Caught 10
Starting 0
Returing 0
Stopping 0
>> fourth

答案 3 :(得分:0)

这可行吗?

int save = -10000000000;
int param;
int result;

int isolated(int p) {

  if (save != -10000000000)
  {  
    // run the other condition
  }
  else
  {  
     save  = p;
     param = p;
     try {
        // make calculations with "param" and place the
        // result into "result"
        process();
        return result;
     } catch (...) {
       return 0;
     }
  }
}

答案 4 :(得分:0)

如果我理解正确,您希望在功能结束时自动将运行标志设置为false。如果这是要求,那么您可以使用链接中提到的ScopeGuard赞成。