1

以下のコードの場合、結果は「EA Exception Finished」です。これは、派生クラスでスローしたにもかかわらず、基本クラスによってキャッチされたことを意味します。いつもですか?もしそうなら、どうすれば派生クラスをキャッチさせることができるので、「EB Exception Finished」が表示されますか?

throw EB()また、とが何を意味するのか正確にはわかりません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

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 に答える
1

理由:

アップキャスティング

派生クラスからベースへ。したがって、常に最初のキャッチで立ち往生します。

于 2016-09-19T06:11:10.163 に答える