【问题标题】:Why catch block of base class is catching the exception when I am throwing object of derived class? [duplicate]当我抛出派生类的对象时,为什么基类的 catch 块会捕获异常? [复制]
【发布时间】:2017-01-08 13:14:42
【问题描述】:

如果我传递派生类的对象,那么应该调用派生类的 catch 块。但是输出表明异常被基类捕获。为什么?

#include<iostream>
using namespace std;

class Base {};
class Derived: public Base {};
int main()
{
   Derived d;
   // some other stuff
   try {
       // Some monitored code
       throw d;
   }
   catch(Base b) { 
        cout<<"Caught Base Exception";
   }
   catch(Derived d) {  //This catch block is NEVER executed
        cout<<"Caught Derived Exception";
   }
   getchar();
   return 0;
}

【问题讨论】:

  • 你应该移动带有派生大小写的catch,然后是基数。它们没有超载。
  • 不是骗子,catch 子句不同。
  • 是的,这是对第二个问题的欺骗,在我发表评论时尚未链接到该问题。

标签: c++ inheritance exception-handling


【解决方案1】:

标准说(以工作草案的[except.handle]/4]为例,强调我的):

try 块的处理程序按出现的顺序进行尝试。 [ 注意:这使得编写永远无法执行的处理程序成为可能,例如,通过将最终派生类的处理程序放置在对应的明确公共基类的处理程序之后.

这正是您在代码中所做的。
因此,无论您的期望是什么,我都会说这是预期的行为。

请注意,您可以交换两个处理程序来解决问题。

【讨论】:

  • @CodyGray 有趣。老实说,我不记得那个答案,但有趣的是,我遵循了更多或更少的相同模式。我应该删除这个吗?没问题。
  • 不,您不必删除。我只在搜索一个问题以将其作为副本关闭时才看到您的答案。已经完成了关闭,所以一切都很好。我只是觉得看到你保持一致可能会很有趣。 :-)
【解决方案2】:

关于这个有一点要说的。

首先,通过引用而不是值来捕获异常是一种很好的做法。这可以防止在派生异常对象的情况下对其进行切片。这不是特定于异常,而是继承的一般特征。

讨论了这种现象的描述here

另外,正如另一个答案所指出的,如果您坚持以这种方式做事,则需要更改 catch 的顺序,因为派生类满足基本 catch 块。还有另一种方法可以显式使用此属性:只需让基类捕获所有内容。你可以使用它,除非派生异常有一个非常具体的特性需要单独处理

【讨论】:

    【解决方案3】:

    按顺序检查 catch 子句 - 你得到第一个匹配项,而不是最佳匹配项。

    所以首先检查派生类型会发现这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-18
      • 2019-04-29
      • 1970-01-01
      • 2017-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多