2017-04-14 2 views
1

私はPlayerオブジェクトを持っています。そのオブジェクトはそのコンストラクタ内で例外をスローする可能性がありますので、私の主な機能ではtryブロックの中に2 Playerオブジェクトを作成しています。 私はそのようなstd::arrayにおけるこれら2つのPlayer S格納したい:問題は、私はtryブロックの外に配列を使用することはできないだろうということです、と私はすべてのmainを置くことを聞いたC++ tryブロックのオブジェクトを作成してstd :: arrayに格納します

try 
{ 
    Player p1(10, 10, ikazuchi); 
    Player p2(70, 10, hibiki); 
    std::array<Player, 2> players = {p1, p2}; 
} 

をtryブロック内のコードはしばしば悪い考えです。

p1p2がそこに存在しないため、私はstd::arrayをtryブロックの後に宣言できません。

std::vectorで問題を解決できますが、コンパイル時にアレイのサイズを知っているときにはstd::arrayを使用する方が良いと読んだことがあります。

デフォルトのコンストラクタを作成してオブジェクトを作成し、tryブロック内にそれらを埋め込むことができましたが、コンストラクタですべてを作成する方が適切なようです。

そのためのベストプラクティスは何ですか?

+0

あなたはどんなエラーをキャッチしようとしていますか? –

+0

tryブロックの外側に配列を宣言していない理由を再説明するか、言い換えることができますか? tryブロックの外側に宣言することができ、tryブロックの内部にプレーヤーを格納することができるからです。 – Eddge

+0

'Player'は移動できませんか? – Jarod42

答えて

1

ダイナミックアロケーションなどを使用して、いつでもboost::optional<std::array<Player, 2>>のような問題を回避することができますが、実際の問題は次のとおりです。つまり、プレーヤーオブジェクトの1つが構築に失敗し、例外がスローされたとします。その後、players配列で何をしますか?それは法的な状態ではなく、少なくとも例外がスローされなければそれが期待される状態にはありません。

tryの範囲を大きくすることに問題はありません。それは、例外があなたの進歩を妨げるすべてのものをカバーするべきです。物理的にたくさんのソースコードがあるのが好きでない場合は、コードを関数に移動します。とにかく、これは良いアイデアかもしれません。すべてがうまくいくと仮定し、エラーを処理することが主な役割を果たす関数です。

playersの内部オブジェクトが無効な状態(コンストラクタが投げられた状態)にある場合、意味のある方法がある場合は、その状態のオブジェクトを最初に配置することができます(tryブロック)、tryの中にそれらを割り当ててください。

質問は、あなたが不要なデフォルトコンストラクタを提供したくないと述べたが、私はどちらかplayertryの内側に属していることを主張し、またはPlayerはデフォルトコンストラクタ(または「正しく初期化されていません表現の同等の方法)が必要です。

+0

tryブロックが私のコード全体をカバーするのは問題ではありませんか?私のプレーヤーのオブジェクトは私のイベントループで使用されるので...例外をキャッチしない方が良いでしょうか? – Xwilarg

+3

@ Xwilarg「tryの全コードが悪い」といったような徹底的なルールについて考えることはできません。それらは教義ではありません。あなたはそれらを理解し、あなたのコードを理解する必要があります。コードがオブジェクトなしで機能できない場合は、例外を作成してログに記録して正常に終了させるだけです。 – Angew

2

以下のようにすることができます。

int main() { 
    std::array<int, 2> array; 
    try { 
    array[0]=1; 
    array[1]=1; 
    } catch (...) { 
    } 
    return 0; 
} 

利用Playerの代わりint

+1

私はそれをしようとしましたが、tryブロック内にあるので、私は次のエラーがあります:削除された関数 'std :: arrayの使用 :: array()' – Xwilarg

+0

@ xwilarg tryブロックの外側にp1とp2を使用する場合Playerのオブジェクトの代わりにPlayerのポインタを使用する必要があります。 –

+1

@ManthanTilvaは必ずしもそうではありません。あなたが割り当てたときにそれをコピーして配列にコピーします。 – Eddge

0

あなたのプレイヤーがコピー/移動され、自明に構成されている場合は、配列を作成して割り当てます。

std::array<Player, 2> players; 
try{ 
    players[0]=Player(10, 10, ikazuchi); 
    players[1]=Player(70, 10, hibiki); 
} catch ... 

代わりにあなたが行うことができます:

std::optional<std::array<Player, 2>> players; 
try{ 
    Player p1(10, 10, ikazuchi); 
    Player p2(70, 10, hibiki); 
    players.emplace(std::array<Player, 2>{{std::move(p1),std::move(p2)}}); 
} catch ... 

いますが、ブーストのオプションのように、オプションの非C++ 17のバージョンを確認する必要があるかもしれません。

別のアプローチは、次のとおりです。

auto players = [&]()->std::array<Player, 2>{ 
    try { 
    Player p1(10, 10, ikazuchi); 
    Player p2(70, 10, hibiki); 
    return {{std::move(p1),std::move(p2)}}; 
    } catch (some_error){ 
    throw some_other_error; 
    } 
}(); 

が、これは、配列またはスローのいずれかによって終了する必要があります。

+0

OPが述べるように、 'Player'にはデフォルトのctorがありません。最初のオプションは機能しません。 – Angew

関連する問題