8

コンストラクターが例外をスローする可能性のあるクラスがあります。

class A {
    A() { /* throw exception under certain circumstances */ }
};

スタックに割り当てられたインスタンスのクライアントでこの例外をキャッチしたいと思います。tryしかし、少なくともインスタンスが生きている必要がある限り、ブロックを拡張することを余儀なくされています。

try {
    A a;
    do_something(a);
} catch {
    // ...
}

これは、tryブロックが大きすぎて例外の原因を追跡できない場合に、明らかに問題になります。

try {
    A a1;
    A a2;
    do_something(a1, a2);
} catch {
    // Who caused the exception?
}

この状況を回避するにはどうすればよいですか?

更新

問題をうまく説明していなかったようです。明らかな理由から、tryブロックを必要なだけ少ないコード(つまり、構造のみ)にまたがらせたいと思います。

しかし、それは、オブジェクトがスコープ外に移動したために、後でオブジェクトを使用できないという問題を引き起こします。

try {
    A a1;
} catch {
    // handle a1 constructor exception
}
try {
    A a2;
} catch {
    // handle a2 constructor exception
}

// not possible
do_something(a1, a2);
4

3 に答える 3

7

変更を必要としない解決策Aは、ネストされたtry/catchブロックを使用することです。

try {
    A a1;
    try {
        A a2;
        do_something(a1, a2);
    }
    catch {
      // a2 (or do_something) threw
    }
} catch {
    // a1 threw
}

ただし、可能であればこれを避ける方がおそらく良いでしょう。

于 2013-01-07T21:28:24.927 に答える
4

スタック構築オブジェクトの代わりにヒープ構築オブジェクトを使用して、どのオブジェクトが正常に構築されたかをテストできるようにします。例:

// or std::unique_ptr in C++11, or boost::unique_ptr ...
std::auto_ptr<A> a1_ptr;
std::auto_ptr<A> a2_ptr;

A *a1 = NULL;
A *a2 = NULL;

try
{
    a1 = new A;
    a1_ptr.reset(a1);
}
catch (...)
{
}

try
{
    a2 = new A;
    a2_ptr.reset(a2);
}
catch (...)
{
}

if( (a1) && (a2) )
    do_something(*a1, *a2);

または(Aコピーで作成できる場合のみ):

boost::optional<A> a1;
boost::optional<A> a2;

try
{
    a1 = boost::in_place<A>();
    a2 = boost::in_place<A>();
}
catch (...)
{
    //...
}

if( (a1) && (a2) )
    do_something(*a1, *a2);
于 2013-01-07T21:28:21.067 に答える
0

状況によっては便利な別のアプローチ:

class ExceptionTranslatedA : public A {
public:
    template<typename Exc>
    ExceptionTranslatedA(Exc exc)
    try : A() {}
    catch (unhelpful_generic_exception) {
        throw exc;
    }
};

これは、別の例外をスローするだけで元のtry-catchブロックで実行したい場合に特に役立ちます。これは、例外を完全に取り除くことができるためです。また、制御フローにブール変数を導入するよりもいくらかエレガントに感じます(boost::optionalsに隠されている場合でも)。

于 2015-12-12T00:09:12.613 に答える