C++ 例外 元の例外の再スローに関する質問 質問する

C++ 例外 元の例外の再スローに関する質問 質問する

catch 内の次の append() により、再スローされた例外で、呼び出された append() の効果を確認できますか?

try {
  mayThrowMyErr();
} catch (myErr &err) {
  err.append("Add to my message here");
  throw; // Does the rethrow exception reflect the call to append()?
}

同様に、このように書き直すと、実際の例外が myErr によって派生した場合にビット スライスが発生しますか?

try {
  mayThrowObjectDerivedFromMyErr();
} catch (myErr &err) {
  err.append("Add to my message's base class here");
  throw err; // Do I lose the derived class exception and only get myErr?
}

ベストアンサー1

どちらの場合も、参照でキャッチするので、元の例外オブジェクトの状態を事実上変更することになります(これは、その後の巻き戻し中に有効なままになる魔法のメモリ位置--0x98e7058下の例では、

  1. 最初のケースでは、 で再スローするためthrow;( とは異なりthrow err;、 の「魔法の場所」にある元の例外オブジェクトが、変更を加えて保持されます0x98e7058)、意思append() の呼び出しを反映する
  2. 2番目のケースでは、明示的に何かを投げるので、コピーerrが作成され、その後、新たにスローされます (異なる「魔法の場所」で0x98e70b0-- コンパイラーが認識している限りでは、は の「魔法の場所」ではなく の のようerrに、スタック上に巻き戻されようとしているオブジェクトである可能性があるため)。e0xbfbce4300x98e7058派生クラス固有のデータが失われます基本クラスインスタンスのコピー構築中。

何が起こっているかを説明する簡単なプログラム:

#include <stdio.h>

struct MyErr {
  MyErr() {
    printf("  Base default constructor, this=%p\n", this);
  }
  MyErr(const MyErr& other) {
    printf("  Base copy-constructor, this=%p from that=%p\n", this, &other);
  }
  virtual ~MyErr() {
    printf("  Base destructor, this=%p\n", this);
  }
};

struct MyErrDerived : public MyErr {
  MyErrDerived() {
    printf("  Derived default constructor, this=%p\n", this);
  }
  MyErrDerived(const MyErrDerived& other) {
    printf("  Derived copy-constructor, this=%p from that=%p\n", this, &other);
  }
  virtual ~MyErrDerived() {
    printf("  Derived destructor, this=%p\n", this);
  }
};

int main() {
  try {
    try {
      MyErrDerived e;
      throw e;
    } catch (MyErr& err) {
      printf("A Inner catch, &err=%p\n", &err);
      throw;
    }
  } catch (MyErr& err) {
    printf("A Outer catch, &err=%p\n", &err);
  }
  printf("---\n");
  try {
    try {
      MyErrDerived e;
      throw e;
    } catch (MyErr& err) {
      printf("B Inner catch, &err=%p\n", &err);
      throw err;
    }
  } catch (MyErr& err) {
    printf("B Outer catch, &err=%p\n", &err);
  }
  return 0;
}

結果:

  Base default constructor, this=0xbfbce430
  Derived default constructor, this=0xbfbce430
  Base default constructor, this=0x98e7058
  Derived copy-constructor, this=0x98e7058 from that=0xbfbce430
  Derived destructor, this=0xbfbce430
  Base destructor, this=0xbfbce430
A Inner catch, &err=0x98e7058
A Outer catch, &err=0x98e7058
  Derived destructor, this=0x98e7058
  Base destructor, this=0x98e7058
---
  Base default constructor, this=0xbfbce430
  Derived default constructor, this=0xbfbce430
  Base default constructor, this=0x98e7058
  Derived copy-constructor, this=0x98e7058 from that=0xbfbce430
  Derived destructor, this=0xbfbce430
  Base destructor, this=0xbfbce430
B Inner catch, &err=0x98e7058
  Base copy-constructor, this=0x98e70b0 from that=0x98e7058
  Derived destructor, this=0x98e7058
  Base destructor, this=0x98e7058
B Outer catch, &err=0x98e70b0
  Base destructor, this=0x98e70b0

以下も参照:

おすすめ記事