1

クラス AI には、n ミリ秒ごとに数百回または数千回アクセスする必要があるメンバーが 1 つあります。たとえば、何かを描画するには LPDIRECT3DDEVICE3D にアクセスする必要があります。

以前はグローバルがありましたが、それは正しくないようです。私の調査で、OPの質問に対する次の回答が見つかりました。

jalf : 「それはつらいので、モーニング コールです。私は何か間違ったことをしています。その多くのオブジェクトは、スクリーン バッファについて知る必要はありません。どうすればこれを修正できますか?`)」 @ this answer alinea 8

基本的に、そのようなグローバル変数の扱い方を知りたいのですが、他にどのようなオプションがありますか?

4

3 に答える 3

0

あなたの選択はこれに要約されます: 関数がデータを必要とする場合、そのデータは:

  1. パラメータとして関数に渡されるか、または
  2. 関数が効果的にクエリできる場所に配置してください。

(3. は無視するか、関数自体によって生成されます。)

合格したい場合A::memberは、いくつかのオプションがあります。データをコンテキスト オブジェクトに入れて渡すことができます (これは、渡したいメンバーが少数ある場合に効果的であり、単体テストが存在する場合にうまく機能します)。データを関数に直接渡すことができます。データを何かに渡して、それを関数に渡すことができます。メッセージ パッシングを使用できます。パブリッシュ/サブスクライブ キューなど、より間接的なメカニズムを使用できます。そのような仲介者が渡すデータの種類についてどの程度の知識を持っているかを選択できます。これらはすべて、ある場所から別の場所にデータを渡すときに、ソース、トランスポート、および宛先の間のさまざまな種類の結合を意味します。せいぜいこの結合は、大規模な環境では苛立たしいものになる可能性があります。最悪の場合、これは重大な設計またはセキュリティ上の欠陥になる可能性があります。

A::memberクエリできる場所に配置したい場合は、いくつかのオプションもあります。グローバル変数は 1 つです。アクセス可能なデータ ストア (ファイル、データベース、サービス、キャッシュ、HTTP リソースなど) は別のものです。これらにはそれぞれ意味があります。誰がどのようにデータにアクセスできるかを考慮する必要があります。アクセスが簡単な場合 (グローバル変数のように)、データのクライアントを壊さずにシステムを進化させる方法に問題があります。コードをテストするときに問題が発生する場合もあります。せいぜいこの結合は、大規模な環境では苛立たしいものになる可能性があります。最悪の場合、重大な設計上の欠陥となり、実質的にテスト不可能なコードになる可能性があります。

データを渡したいが、それを渡す必要がある場所の数が気に入らない場合は、データを必要とする関数の数を制限するという別のアプローチがあります。つまり、コードを統合して、実際にA::member. Facade、Bridge、Observer、Abstract Base Class などのさまざまなパターンが、言語レベルで役立つ場合があります。Publish-Subscribe や Callback などのアーキテクチャ パターンも役立つ場合があります。インスピレーションを得るため、デカップリングリファクタリング、および依存関係の排除のトピックを調べてください。

では、正しい方法はどれでしょうか?唯一の正しい方法はありません。特定のケースを見て、そのケースのオプションとトレードオフを比較検討し、最も気に入ったものを選択する必要があります。

于 2012-08-15T23:35:42.443 に答える
0

私が考えることができる 1 つのことは、その A::member にアクセスする必要があるすべての関数に渡すことですが、それはばかげた量になります。

多くのアプローチがあります。それらは、毎日使用するプログラムのいたるところにあります。

  • あなたは参照を保持することができます
  • 参照を渡します(あなたが述べたように)
  • 場合によっては複数のインスタンスを使用する
  • メソッドを使用して、メソッドを呼び出すには実際には 3 回の呼び出しが必要であるという事実を抽象化します (最小知識の原則)。
  • より小さく、より専門的なオブジェクトを使用する
  • 他の形式の抽象化および/またはラッピングを検討してください
  • いくつかの場所で他の設計パターンを検討する

プログラムの作成を開始するだけです-結合が高くなる可能性があるため、やみくもにではありません-使用パターンを観察し、それに応じてリファクタリングおよび再構築します。これが、グローバルが悪い理由の 1 つです。ルートを解除するのは非常に困難ですが、これは、多くの参照を持つグローバルを削除するときに実行しなければならないプロセスです。

于 2012-08-15T08:30:08.853 に答える
0

良いアプローチの 1 つは、構築時に A::member を使用して自分自身をデータ構造 (弱いまたは生のポインターのベクトル、ポインターのマップなど) に登録したいオブジェクトを用意し、次に A: を適用するときにオブジェクトを作成することです。 :member を各オブジェクトに追加すると、登録されているすべてのオブジェクトをループして、それぞれのリクエストを処理できます。ここでグローバルを使用すると、罠に陥りやすいことに注意してください。回避するようにしてください。

さまざまな型 (継承階層なし) のオブジェクトがある場合は、型消去を使用して、A::member を受け取り、そのオブジェクトに適用する各オブジェクトの関数ポインター (または boost::function のような関数オブジェクト) を格納できます。これにより、任意の抽象オブジェクトが x 個のオブジェクトの型を知る必要なく A::member を使用できるようになります。一致する関数を取得することは、同様の形式のメンバー関数を各オブジェクトに追加するか、boost::bind を実行して、一致する形式に作業を行う呼び出しをラップするのと同じくらい簡単です。

このアプローチにより、多くのボイラープレート コードが不要になり、特定の通知時間にすべてのユーザーが A::member を使用できるように、さまざまな新しいオブジェクト タイプを簡単に拡張できます。

于 2012-08-14T20:26:16.503 に答える