【问题标题】:Catch clauses not catching right?捕获子句不捕获对吗?
【发布时间】:2013-10-24 16:33:38
【问题描述】:

我只是在学习如何在 C++ 中使用异常,并且在我的“测试”代码中遇到了奇怪的行为。 (请原谅像这样的过于愚蠢的问题......这不是缺乏研究/努力,只是缺乏经验!)如果我只是捕捉到例外DivideByZero 它工作正常。

但是引入第二个异常StupidQuestion 会使代码无法完全按照我的预期工作。我是如何在下面写的.但是,如果我输入 a=3b=1,程序将重定向到 DivideByZero try 子句而不是 StupidQuestion 子句。不过,奇怪的是,divide 似乎确实在抛出 StupidQuestion(参见 cout 声明),但它并不正确,cout 声明的缺失也可以看出这一点。

#include <iostream>
#include <cstdlib>
using namespace std;
const int DivideByZero = 42;
const int StupidQuestion=1337;
float divide (int,int);
main(){
       int a,b;
       float c;
       cout << "Enter numerator: ";
       cin >> a;
       cout << "Enter denominator: ";
       cin >> b;
       try{
           c = divide(a,b);
           cout << "The answer is " << c << endl;
           }
       catch(int DivideByZero){
                           cout << "ERROR: Divide by zero!" << endl;
                           }
       catch(int StupidQuestion){
                                 cout << "But doesn't come over here...?" << endl;
                             cout << "ERROR: You are an idiot for asking a stupid question like that!" << endl;
                             }
       system("PAUSE");
       }

float divide(int a, int b){
      if(b==0){
               throw DivideByZero;
               }
      else if(b==1){
               cout << "It goes correctly here...?" << endl;
               throw StupidQuestion;
               }
      else return (float)a/b;
}

我想知道这是否与 DivideByZeroStupidQuestion 都是 int 类型有关,所以我更改了代码以使 StupidQuestion 的类型为 char 而不是 int。 (所以:const char StupidQuestion='F';catch(char StupidQuestion) 是上面唯一改变的东西)而且效果很好。

当两个异常具有相同的类型 (int) 时,为什么上面的代码不起作用?

【问题讨论】:

  • 异常是按类型而不是按名称捕获的。所以两者都是 int 类型,第一个处理程序将捕获它们。如果您想区分它们,请将第二个设置为不同的类型。
  • @Duck:这将是我赞成的答案。
  • 有什么理由不创建从异常继承的类并改用这些类?这比抛出随机类型更好地遵循模式

标签: c++ exception


【解决方案1】:

不是这个

catch(int DivideByZero) {
    cout << "ERROR: Divide by zero!" << endl;
}
catch(int StupidQuestion) {
    cout << "But doesn't come over here...?" << endl;
    cout << "ERROR: You are an idiot for asking a stupid question like that!" << endl;
}

你正在寻找

catch (int errval) {
    if (errval == DivideByZero) {
        cout << "ERROR: Divide by zero!" << endl;
    }
    else if (errval == StupidQuestion) {
        cout << "ERROR: You are an idiot for asking a stupid question like that!" << endl;
    }
    else {
        throw; // for other errors, keep searching for a handler
    }
}

catch 子句中的变量名正在创建一个新的局部变量,它与同名的全局常量无关。

另外请注意,没有办法只捕获一个错误号...但是您可以按照我的说明重新抛出未知错误。

【讨论】:

    【解决方案2】:
    catch(int DivideByZero)   { }
    catch(int StupidQuestion) { }
    

    catch 块都捕获 ints,它们只是名称不同。只能输入第一个,第二个是死码。

    【讨论】:

    • 如果它们只按类型命名,那么命名它们有什么意义(就像我在教程中看到的那样)?然后我必须为每个 catch 子句声明/使用一个新类型???这似乎有点啰嗦......
    • @Thornshadow17432:链接教程,我们需要更多上下文。
    • @Thornshadow17432 就像调用函数一样。它将值传递给您并将其存储在该变量中,以便您可以在块中使用它。比如catch( string ex ){ cerr &lt;&lt; ex &lt;&lt; endl; }
    • 命名它们的目的是让您可以按名称引用它们,就像命名程序中的任何其他变量一样。这一点尤其重要,因为正如您现在所了解的,我们是按类型而不是按特定值来捕获事物的。多个不同的异常都可以具有不同的值但类型相同。您需要阅读它们的值以确定有关它们的详细信息。当您开始抛出 时,这变得更有价值,因为您可以使用继承来捕获许多相关类型的对象。
    • @Thornshadow17432 “这似乎有点啰嗦”——但实际上并没有。事实证明,您不需要太多不同的异常类型,它们大多是重复出现的相同类型。
    【解决方案3】:

    在为异常选择处理程序时,只考虑类型,既不考虑值也不考虑地址(变量的地址在这里根本不适用,因为异常是如何工作的),编译后变量的名称也不存在。 总是选择第一个适当的异常处理程序。

    详情请看我对另一个问题的回答:https://stackoverflow.com/a/45436594/1790694

    【讨论】:

      猜你喜欢
      • 2013-07-24
      • 2019-06-29
      • 2013-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多