【问题标题】:Why throw at derived class catches by base?为什么要按基数抛出派生类捕获?
【发布时间】:2016-09-16 09:25:28
【问题描述】:

对于下面的代码,结果是“EA Exception Finished”,这意味着虽然我们抛出了派生类,但它被基类捕获。总是这样吗?如果是这样,我怎样才能使派生类捕获,从而出现“EB Exception Finished”?

我也不知道throw EB()catch(EA&) 是什么意思。 catch(EA&) 是否意味着 catch 块获取 EA object 的引用?

对不起,我的无知。如果您向我推荐一本书或有关异常结构的参考资料,那将很有帮助。

class EA {};
class EB: public EA {};

void F()
{
  throw EB();  // throw at EB().
}

int main()
{
  try
  {
    F();
  }
  catch(EA&) // caught here??
  {
    std::cout<<"EA Exception";
  }
  catch(EB&) // why not me? every time?
  {
    std::cout<<"EB Exception";
  }

  std::cout<<" Finished"<<std::endl;

  return 0;
}

【问题讨论】:

  • 异常总是被 first 捕获块捕获,可以捕获它,所以你的顺序是错误的。
  • 非常感谢您的回答!!!

标签: c++ exception-handling try-catch throw catch-block


【解决方案1】:

更改 catch 块的顺序以修复该行为:

#include <iostream>

class EA {};
class EB: public EA {};

void F()
{
  throw EB();  // throw at EB().
}

int main()
{
  try
  {
    F();
  }
  catch(EB&) // why not me? every time?
  {
    std::cout<<"EB Exception";
  }
  catch(EA&) // caught here??
  {
    std::cout<<"EA Exception";
  }

  std::cout<<" Finished"<<std::endl;

  return 0;
}

编译器甚至会警告您:

main.cpp:21:3: warning: exception of type 'EB' will be caught
   catch(EB&) // why not me? every time?
   ^~~~~
main.cpp:17:3: warning:    by earlier handler for 'EA'
   catch(EA&) // caught here??
   ^~~~~

【讨论】:

  • 非常感谢!在这种情况下 throw EB() 是什么意思?你用什么编译器?
  • @DongkyuChoi 我在coliru使用了GCC
【解决方案2】:

正如[except.handle](工作草案)中的标准所述:

try 块的处理程序按出现的顺序进行尝试。这使得编写永远无法执行的处理程序成为可能,例如,将派生类的处理程序放在相应基类的处理程序之后。

这正是你所做的。确实很有趣。
反转处理程序以解决问题。

【讨论】:

    【解决方案3】:

    原因:

    向上转型

    派生类到基类。因此总是卡在第一个钓点上。

    【讨论】:

      【解决方案4】:

      因为 catch 块按照您声明它们的顺序进行检查。

      你首先赶上EA&amp;。 EB 派生自 EA,因此这是一个有效的捕获,第二个捕获被忽略。

      您希望首先拥有最“专业”的异常捕获。因此,如果您切换 catch 块,它应该以另一种方式工作。

      【讨论】:

      • 非常感谢!那么抛出到派生类也可以被基类捕获,但是因为不能做特化处理所以不可取?
      • 改变“catch”块的顺序就可以了。也如另一个答案中所述。在这些情况下,您应该收到警告。
      【解决方案5】:

      catch 语句按顺序检查。 EA&amp; 匹配,所以使用它。 EB&amp; 永远无法匹配。您需要先提出更具体的问题。

        catch(EB&) // Will catch
        {
          std::cout<<"EB Exception";
        }
        catch(EA&) // and this would catch EA objects that aren't EB.
        {
          std::cout<<"EA Exception";
        }
      

      【讨论】:

      • 非常感谢!那么EB先捕获,然后EA也随之捕获?
      • 没有。仅执行第一个匹配的 catch 块。对于特定异常、const std::exception&amp;...,有一个 catch 块是很常见的。每次打印先后顺序不太详细的信息。
      猜你喜欢
      • 1970-01-01
      • 2015-07-18
      • 2012-09-18
      • 2021-09-25
      • 1970-01-01
      • 2017-04-26
      • 2012-04-07
      • 2017-12-18
      • 1970-01-01
      相关资源
      最近更新 更多