【问题标题】:In C++ leave scope when error occurs without exceptions在 C++ 中,当无异常发生错误时离开范围
【发布时间】:2019-09-01 19:28:53
【问题描述】:

在 bash 中我们可以说:

(
set -e
function OnError {  caller | { read line file; echo "in $file:$line" >&2; };  }
trap OnError ERR  ## catch exception
echo hello  ## step 1
false
echo "never come here" 
)
# continue here

每个命令都返回退出代码。标志 -e 告诉 bash 检查每个结果,如果结果不为零则退出。
C++ 中的异常提供了类似的逻辑:

#include <iostream>
using namespace std;

void step1(){
    cout<<"hello"<<endl;
}
void step2(){
    throw std::runtime_error("step2 always fail");
}
void step3(){
    cout<<"never come here"<<endl;
}

int main(){
   try{
      step1();
      step2();  // throws
      step3();  // never come here
   }catch(...){
      cerr<<"caught error"<<endl;
   }
   // continue here
}

这也是一样的。但是需要额外的操作来检测异常是从哪里引发的。

C++ 开发人员通常拒绝使用带有-fno-exceptions 的异常。并且代码看起来像 C - 需要检查每个操作的结果。

#include <iostream>
using namespace std;

int step1(){
    cout<<"hello"<<endl;
    return 0;
}
int step2(){
    return -1;
}
int step3(){
    cout<<"never come here"<<endl;
    return 0;
}

#define CHECK(err,msg) \
    if(err){ \
       cerr<<"error in "<<msg<<endl; \
       break; \
    }

int main(){
    while(0){
      CHECK(step1(),"step1");
      CHECK(step2(),"step2");
      CHECK(step3(),"step3");
    }
    // continue here;
}

这看起来有点麻烦。但是这里我们可以直接跟踪file:line。

我想要没有例外的干净代码。喜欢:

#include <iostream>
using namespace std;

enum Result {SUCCESS,FAIL};

Result step1(){
    cout<<"hello"<<endl;
    return SUCCESS;
}
Result step2(){
    return FAIL;
}
Result step3(){
    cout<<"never come here"<<endl;
    return SUCCESS;
}

int main(){
   {
    step1();  // success
    step2();  // fail , interrupt execution and go out of scope
    step3();  // never come here
   }
   // continue here
}

如何实现与 bash 中相同的行为,保持代码简洁干净,没有例外?

【问题讨论】:

  • 您的例外有什么问题?无论您是否try catch,它都能满足您的需求。
  • Qt 不使用异常。他们有理由。人们也不会在嵌入式系统中使用异常。这是一场圣战。无论如何想象 -fno-exceptions 是某些团队/环境/项目中的约定。
  • 有一个 boost 结果库和一组宏,可让您在调用失败时退出范围,但这需要您重写应用程序。 boost.org/doc/libs/1_71_0/libs/outcome/doc/html/tutorial/…

标签: c++ exception


【解决方案1】:

您可以(ab)使用 C++ 使用惰性求值来检查布尔逻辑这一事实:

#include <iostream>
using namespace std;

bool step1(){
    cout<<"hello"<<endl;
    return true;
}
bool step2(){
    return false;
}
bool step3(){
    cout<<"never come here"<<endl;
    return true;
}

bool executeSteps() {
    return step1() && step2() && step3();
}

int main(){
    executeSteps();
}

由于step2() 返回false,整个条件无法评估为true,因此甚至不检查其余部分。

您甚至不需要单独的函数(尽管忽略布尔计算的结果可能会让读者感到困惑):

int main(){
    step1() && step2() && step3();
}

【讨论】:

  • @kyb 听起来您真的想使用异常。异常可以告诉您what() 出错了(您可以轻松调试它们)。更好的是,您可以抛出多种类型的异常,并让 type 告诉您出了什么问题,而不是字符串。
  • 当然,您可以使用枚举进行上述操作(其中只有一个成功状态等于0)并改用||,但这使得结果集仅限于枚举。
【解决方案2】:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多