0

趣味でソフトウェア プロジェクトに取り組んでいるとき、設計プロセス中に進行が遅くなったり、完全に停止したりすることが何度もありました。通常、以前に遭遇したのと同じ問題に出くわします。このような繰り返し発生する問題の 1 つは、オブジェクトがどのオブジェクトと接触する必要があるか、またはどのオブジェクトがそれを所有しているかをオブジェクトに知らせることです。

Corporationという名前のクラスのインスタンスがありstartup、1 つのクラスSupervisorオブジェクトと複数のクラスEmployeeオブジェクトが機能するとします。スーパーバイザーは、従業員にタスクを割り当て、従業員が支援を求めたときに支援する責任があります。しかし、従業員は、割り当てられた作業を完了したことを報告したり、何かを依頼したりするために、上司が誰であるかを知る必要があります。

問題は、この上司が誰であるかを従業員にどのように知らせるかです。私はいくつかの解決策を考え出しましたが、どれも決定的な答えのようには思えません。

  1. インスタンスをSupervisorグローバルにアクセスできるようにし、すべてEmployeesそのインスタンスを直接呼び出すようにします。グローバルを避けることは一般的には良い考えですが、これは例外でしょうか? 私はそうは思いませんし、startup複数のマネージャーを持つようになった場合、問題が発生するでしょう。
  2. static Supervisor *supervisorクラスへのメンバーの追加Employee: これにより、グローバル アクセスの使用とそれに関連する問題が回避されますが、従業員がstartup成長したときに別のマネージャーに報告することができなくなります。
  3. Supervisor *supervisorクラスにメンバーを追加し、従業員のコンストラクターのパラメーターとしてそれぞれへのポインターをEmployee渡す: 非常に柔軟ですが、メンバー変数が多くない場合、メモリ使用量の点で非効率的です。SupervisorEmployeeEmployee
  4. 誰が誰であるかを知る必要があるメンバー関数Supervisorのすべての呼び出しで、ポインターをパラメーターとして渡す: 最も柔軟ですが、おそらく解決策 3 よりも効率が悪く、ほとんどすべてのメンバー関数がスーパーバイザー パラメーターを必要とするため、追加のオーバーヘッドと不要な依存関係。EmployeeEmployeesupervisor
  5. Employee型以外の引数を 1 つ持つクラス テンプレートを作成するSupervisor *S: これは、ソリューション 1 または 2 と同じくらい効率的ですが、より柔軟です。ただし、従業員の数はstartup実行時に変更できますがstartup、コンパイル時に追加のスーパーバイザーを作成して非アクティブのままにしない限り、実行時にスーパーバイザーを追加することは不可能です。さらに、引数として異なるが似ている (テンプレートで作成された) タイプの 1 人の従業員を受け取るコピー コンストラクターを作成する方法についてもわかりません。
4

1 に答える 1

1

Employeeへのポインターを与えることSupervisorは、コールバックまたは進行状況レポートを手配するための従来の方法です。(これが解決策の 3 番目です。) ポインタは 1 つだけです。メモリの使用が心配なほど多くの従業員 (つまり、数千人) がいる場合は、ポインターではなく小さなハンドルを使用してサイズを小さくすることができます。つまり、次のようなものです

typedef uint8_t SupervisorHandle;

class Employee {
    private:
    SupervisorHandle s;

    Supervisor& getSupervisor() {
        return startup.getSupervisor(s);
    }
    // ...
};

ハンドルを他のフィールドの周りに適切に配置すると、必要なのは 1 バイトだけで、最大 256 のスーパーバイザーを持つことができます。しかし、これには柔軟性が犠牲になります。つまり、静的Corporationインスタンスに結び付けられ、256 個のスーパーバイザーという明白でない制限が追加されます。

答え 1 と 2 が 1 つの に制限されていることはすでにお気付きSupervisorでしょう。もしそうするなら、なぜクラスを作る必要があるのでしょうか? Supervisorメソッドごとに渡されたオプション 4 は、実際には改善されません。今度は、すべての呼び出しに対してCorporationマップをリンクする必要があり、そのマップを検索する必要がありEmployeeます。Supervisor少しのメモリを節約するためにそのようなオーバーヘッドを導入することは、あなたが必死に不足している場合にのみ行うことです. オプション 5 では、静的に割り当てられた に制限されますSupervisor。また、クラス テンプレートの派生元となるテンプレートのないEmployeeBaseクラスを作成する必要があり、既に継承を使用していない限り、vtable のオーバーヘッドによってメモリの節約が失われます。EmployeeEmployee

于 2013-09-06T09:23:49.613 に答える