【问题标题】:Why is this exact exception thrown in my c++ code?为什么在我的 C++ 代码中会抛出这个确切的异常?
【发布时间】:2019-07-01 12:07:59
【问题描述】:

我正在分析我讲座中的部分代码。 我设法编译它,但我无法理解: 为什么我的程序输出“Wyjatek”和 0 而不是“WyjatekNieoznaczony”?

我很确定应该抛出 WyjatekNieoznaczony(),因为 a=0 和 b=0 也是如此。现在我有点困惑。 请你帮帮我好吗?

class Wyjatek {};
class WyjatekBledny : public Wyjatek {};
class WyjatekNieoznaczony : public Wyjatek {};

double f(double a, double b) {
    if (b == 0) {
        if (a == 0)
            throw WyjatekNieoznaczony();
        else
            throw WyjatekBledny();
    }
    return a / b;
}


double g(double a, double b) throw (int) {
    try {
        return f(a, b);
    }
    catch (WyjatekBledny) {
        cout << "Wyjatek bledny" << endl;
        throw 1;
    }
    catch (Wyjatek) {
        cout << "Wyjatek" << endl;
    }
    catch (WyjatekNieoznaczony) {
        cout << "Wyjatek nieoznaczony" << endl;
        throw;
    }
    return 0;
}

int main()
{
    double a = 0, b = 0;
    try {
        cout << g(a, b) << endl;
    }
    catch (...)
    {
        cout << "Inny wyjatek" << endl;
    }
    system("pause");
    return 0;
}

【问题讨论】:

  • catch 语句从上到下工作。如果给定的catch 可以捕获异常,那么它将被捕获,其余的将被忽略。因为WyjątekNieoznaczony 也是Wyjatek,所以只会执行第二个catch。我正在寻找这个的副本。
  • 我能找到的最接近你的问题stackoverflow.com/questions/29731033/…
  • 附注:用英语编码是一种很好的做法。稍后它将对您有很大帮助,例如,当您需要在 StackOverflow 上提出另一个问题时。不是我们所有人都懂波兰语;)
  • 请在您的帖子中添加适当的缩进,以便我们可以轻松地遵循您的代码。

标签: c++ exception try-catch


【解决方案1】:

是的,确实抛出了 WyjatekNieoznaczony,但在捕获站点,catch (Wyjatek) { 是匹配项(由于继承),因此它被捕获。

捕获站点在行为上更像是 if else 块 - 每个 catch 可能性都按照它们的写入顺序进行考虑 - 而不是 switch 块,您可以在其中将标签放在任何点你喜欢的。

另请注意,通过const 引用而不是通过值来捕获异常是个好主意,否则您可能会遭受对象切片的陷阱。

【讨论】:

  • 非常感谢!我猜这个代码对学生来说应该很棘手。我会记住你的建议!
  • 按值捕获也违背了提前为异常保留内存的目的(尽管这并不是特别重要,除非您捕获的异常是由于内存不足而引发的)。或者......这样的副本被省略了吗?嗯
【解决方案2】:

如果您启用(并阅读)编译器警告,您会遇到以下诊断:

警告:“WyjatekNieoznaczony”类型的异常将被“Wyjatek”的早期处理程序捕获 [...]。

这基本上意味着WyjatekNieoznaczony,通过继承Wyjatek,将首先被catch(Wyjatek) 子句捕获,因为它是可转换的。问题是由于object slicing,它会失去它的Nieoznaczonyness。

我的建议是重新排序catch 子句,这样切片的可能性就消失了(在这种情况下):

catch (WyjatekBledny) {
    cout << "Wyjatek bledny" << endl;
    throw 1;
}
catch (WyjatekNieoznaczony) {
    cout << "Wyjatek nieoznaczony" << endl;
    throw;
}
catch (Wyjatek) {
    cout << "Wyjatek" << endl;
}

【讨论】:

  • 非常感谢!现在我知道我是由继承引起的,我明白了。
  • @SzymonRuciński,没问题!但是,我建议您也查看Bathsheba's answer,并通过const&amp; 而不是按值应用catching。此外,如果答案解决了您的问题,我建议接受它,以便未来的访问者知道它确实是解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-19
相关资源
最近更新 更多