hoge diary - November 4, 2007

[C++] メンバコンストラクタの例外

普段からこれっぽっちも疑問に思わなかったんですが,クラスメンバのコンストラクタの例外をキャッチする方法がある(cppll:3219)とのこと.

構文はこんな感じ.

class Foo
{
  Bar bar;  // Bar クラスは Foo のメンバ (定義は省略)
  Hoge() try : bar() {
    // メンバのコンストラクトが成功したときは,
    // ここに書いた Hoge のコンストラクト処理が行われる
    ...
  }
  catch (...) {
    // メンバのコンストラクタが例外を投げたときはここに来る
    ...
  }     // ←ここで自動的に catch した例外が再度投げられる (VC7 は投げてくれないらしい)
};

こんなところに try-catch が書けたんだ... 全然知らなかった...

メンバコンストラクタが投げた例外は catch 節を抜けた後で自動的に re-throw されるようになっているため,そのクラス自身のコンストラクトも失敗します (cppll:3221 によれば,VC7 では標準の動作をさせるために明示的に再スローしないとダメらしいです.手元に VC7 がないので確認できないのですが).

g++-4 や VC8 (Express Edition) ではどうなるかを試してみることに.

#include <iostream>
#include <stdexcept>

using namespace std;

class B
{
public:
  B() {
    throw runtime_error("hoge");
  }
  ~B() {
    cout << "~B()" << endl;
  }
};

class A
{
public:
  // constructor
  A() try : b() {
    cout << "A()" << endl;
  }
  catch (const exception& e) {
    cout << "foo" << endl;
  }

  ~A() {
    cout << "~A()" << endl;
  }

private:
  B b;
};

int main()
{
  try
  {
    A a;
  }
  catch (const exception& e)
  {
    cout << "bar" << endl;
  }
  return 0;
}

g++-4.1.2 (Gentoo 4.1.2) と,VC8 Express Edition (14.00.50727.42) で試したところ,どちらもいずれの実行結果が得られました.

(g++-4.1.2 での結果)
$ g++ test.cc
$ ./a.out
foo
bar
$
(VC8 Express での結果)
$ cl /nologo /EHsc test.cc
test.cc
$ ./test
foo
bar
$

ちゃんと A のコンストラクトは失敗しており,いずれも標準の動作になっています.

コメント

名前(何でも可):

テキスト(http:// を含む内容は投稿できません):

トラックバック

トラックバック URI: https://www.pakunet.jp/hoge/trackback/2007110401

トラックバックはありません.


Valid XHTML 1.1! Valid CSS!
© 2004-2009 ぱくちゃん.
Last modified: Mon Nov 05 00:17:13 JST 2007