1

私はいくつかの読書をしてきましたが、一般的な意見は、可能な限り2フェーズの初期化を避けるべきだということです。私はそれが言ったことの多くに同意します。しかし、私はそれを簡単に排除できるとは思っていません。

これは、実際のコードに強く基づいていますが、完全に作成された例です-

私がゲームを構築していると想像してください。メイン ゲーム クラスは、3D レンダリングを行う「RenderDevice」オブジェクトを構築する必要があります。ただし、これを構築するには、構成ファイルからいくつかの設定をロードする必要があります。そして、描画する Window オブジェクト。ロガー オブジェクトとメモリ プール。私のコードは、コンストラクターがほとんど機能しないクラスメンバーとしてこれらすべてを配置し、関連するパラメーターを使用して各オブジェクトの init 関数を呼び出します。

// Much simplified code to make a point
Game::Game()
{
    memoryPool_.init(10000000); // Amount of memory to allocate
    logger_.init("logfile.txt", memoryPool_);
    window_.init(2000, 1000);   // Make a nice big window
    renderDevice_.init(window_, logger_, memoryPool_);
}

それは私にはかなりうまくいくようです。しかし、それは二段階です。各オブジェクトは、そのコンストラクターによって部分的にのみ構築されます。したがって、コードを「クリーン」にするために、代わりにこのようなことをしなければなりません。

Game::Game() :
    memoryPool_(1000000),
    logger_("logfile.txt", memoryPool_),
    window_(2000, 1000),
    renderDevice_(window_, logger_, memoryPool)
{
}

そのコードは私にはかなり醜いように見えますが、初期化の順序は、ここにリストされている順序ではなく、クラスで宣言されている順序に依存するため、かなり脆弱です。クラスに追加されるデータが増えると、さらに悪化します。ここでのオブジェクトはいくつかのパラメーターしか必要としませんが、より多くのデータが必要な場合、これはすぐに手に負えなくなります。

各オブジェクトがその仕事をする準備ができているという利点がありますが、私には醜く見え、かなり壊れやすく、エラーが発生しやすいように見えます...

だから私の質問は、私は要点を逃したのですか?これを行うより良い方法はありますか?心配するのをやめてこれを行うべきですか、それともオリジナルのコードを使用するべきですか? それとも、私の設計全体が何らかの形でより高いレベルで間違っているので、質問は役に立ちませんか?

基本的にベストプラクティスとは何ですか?

4

2 に答える 2

8

今、そのコードは私にはかなり醜いようです

私にはそのようには見えません。もしかして慣れてないだけ?

初期化の順序は、ここにリストされている順序ではなく、クラスで宣言されている順序に依存するため、かなり脆弱です

コンパイラの警告をオンにすると、これら 2 つの順序の不一致が通知されるはずです。(Clang にこの警告があることは知っていますが、GCC にもあると確信しています。MSVC についてはよくわかりません。)

ここでのオブジェクトはいくつかのパラメーターしか必要としませんが、より多くのデータが必要な場合、これはすぐに手に負えなくなります。

を使用している場合の違いはわかりませんinit()

于 2013-08-27T21:37:40.580 に答える
0

私の経験では、init関数は、エラーが発生する可能性があり、例外を使用/スローできない場所で使用されます。あなたが言及した例にはすべてエラーケースがあり、戻り値がチェックされていないため、例外がスローされているようです。

コンストラクター自体から init を呼び出すのではなく、Game の init 関数から一連の init を呼び出すことをお勧めします。

于 2013-08-27T22:25:53.063 に答える