2010-07-16 75 views
0

这就是我想要做的(这是一个真正的项目的简化):如何正确实施最终条件?

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()回叫时出现问题。我想知道这种情况,但不知道该怎么做,因为finally在C++中不存在。我觉得我应该使用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.."; 
    } 
} 
+0

我不明白。您想做什么? (假设'finally'存在) – kennytm 2010-07-16 08:33:06

+0

问题是,我应该在* catch和'try'中放置*标志,这显然是代码重复。我现在将延长这个问题 – yegor256 2010-07-16 08:38:53

+0

这是不清楚什么是抛出异常。 – aggsol 2010-07-16 08:46:01

回答

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 
+0

非常感谢,这正是我期待的! – yegor256 2010-07-16 10:48:42

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; 
    } 
    } 
} 
2

也许我没说得对,但你为什么不用标志?你想知道什么时候从process()调用了isolated(),对吗?

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

    // your code here 

    execDeep--; 
} 

现在您可以检查'execDeep'的值,> 1表示它在进程中被调用()时仍然被执行。

5

“finally”类似的情况是在C++中使用guard对象来处理的,它们在析构函数中做了最后的事情。这是恕我直言的更强大的方法,因为你必须分析情况来确定才能创建一个可重用的对象。在这种情况下,我们需要制作流程租赁者,因为参数和回报是以全局方式传递的。解决的方法是在进入时保存它们的值,并在退出时恢复它们:

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; 
    } 
} 
+0

+1以获得良好的RAII。除非你对全局变量(你使用RAII进行处理)使用锁定,否则它不会进行孤立的重入。 – 2010-07-16 09:07:38

+0

单线程可重入吗?递归? – 2010-07-16 09:31:20

0

如果我理解正确的,你要自动设置运行标志设置为false,在函数结尾。如果这是要求,那么你可以使用链接中提到的ScopeGuard