3

多くの場合、次のタスクを達成するために必要です: 何かの状態を変更し、アクションを実行してから、状態を元に戻します。たとえば、Win32 GDI では、背景色を変更し、描画を行ってから色を元に戻す必要があります。

直接行うことができます:

COLORREF oldColor = SetBkColor( deviceContext, newColor );
drawStuff( deviceContext );
SetBkColor( deviceContext, oldColor );

または、コンストラクターで前方変更を行い、デストラクタで後方変更を行うブラケット クラスを介して:

CBkColorSwitcher switcher( deviceContext, newColor );
drawStuff( deviceContext );
//once control reaches end of block the switcher is destroyed and the change is reverted

ブラケット クラスの利点は明らかです。変更の間に例外がスローされた場合、変更は正しく元に戻されます。短所は何ですか?

4

6 に答える 6

12

実際、これはRAIIとして知られ、広く使用されているよく知られた C++ イディオムです。Win32 API は C API であり、実装パターンは異なります。C++ でプログラミングしている場合は、RAII のイディオムを使用してリソースの割り当てと割り当て解除を処理するか、C API にシン ラッパーを記述するか、適切に設計された既存の C++ の置き換えを再利用することをお勧めします。Java プログラマーは、RAII をfinally節の代わりと見なすことができます。

于 2009-08-12T12:34:31.030 に答える
4

いくつかの欠点があります。より多くのコードを記述する必要があり、より多くのオブジェクトを作成することになります。その使用を制御することはできません。間違った使い方をするとメリットを失います。例えば

CBkColorSwitcher * switcher = new CBkColorSwitcher(......)

そうは言っても、利点は欠点をはるかに上回り、ブラケットクラスのアプローチを好むと思います

于 2009-08-12T12:34:50.997 に答える
2

これはベストプラクティスだと思います。欠点は見当たりません(おそらく読みやすさを除いて?)

于 2009-08-12T12:33:29.873 に答える
2

私が見る欠点は次のとおりです(少なくともあなたが与えた例では):

  • コードの読者がブラケット クラスの責任を理解していない限り、実際に何をしているのかはあまり明確ではありません。
  • ブラケット クラスの作成コスト
  • ブラケット クラスを実装するコードを記述すると、それがないバージョンよりも時間がかかります。

そうは言っても、RAII を使用することはこれを行うための「正しい」方法であり、利点は欠点をはるかに上回ります。

于 2009-08-12T12:38:34.603 に答える
1

欠点の 1 つは、通常、新しいクラスを実際に定義する必要があることです。これは、少しオーバーヘッドになる傾向があります。

それはさておき、これは(別の)非常に一般的な RAII の例であり、一般的に非常に優れたアプローチです。

編集:クラスを書く代わりに、関数があるだけの場合は、スコープからの終了時に任意のコードブロックを実行するために使用できます。shared_ptrおそらく、ほとんどのアプリケーションでは少しかわいすぎると思います。

于 2009-08-12T12:34:43.790 に答える
1

私はここでつまらないことをしていますが、:

  1. コード サイズ。例外ハンドラのためにコードが大きくなります。
  2. あらゆる種類のスイッチを処理するには、多くのクラスを作成する必要があります。
  3. より大きなスタック。
  4. 必要がない場合でも、常にすべての例外でコードを実行します (たとえば、アプリケーションをクラッシュさせたい場合など)。
于 2009-08-12T12:42:46.090 に答える