1

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

throw EB()我也无法完全理解and是什么意思catch(EA&)。是否catch(EA&)意味着 catch 块获得 EA对象的引用?

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

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;
}
4

5 回答 5

3

更改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??
   ^~~~~
于 2016-09-16T09:29:26.160 回答
2

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

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

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

于 2016-09-16T18:09:01.900 回答
1

原因:

向上转型

派生类到基类。因此总是被困在第一个渔获物上。

于 2016-09-19T06:11:10.163 回答
1

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

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

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

于 2016-09-16T09:28:40.647 回答
1

catch 语句按顺序检查。 EA&匹配,所以使用它。 EB&永远无法匹配。您需要先放置更具体的捕获。

  catch(EB&) // Will catch
  {
    std::cout<<"EB Exception";
  }
  catch(EA&) // and this would catch EA objects that aren't EB.
  {
    std::cout<<"EA Exception";
  }
于 2016-09-16T09:29:09.297 回答