0

コンポーネント作成用のファクトリ パターンを実装しており、ファクトリによって作成された各タイプのすべてのインスタンスに対してシングルトン コンテナーを実装したいと考えています。理想的には、これはファクトリで作成されたタイプごとに 1 つのベクトルになります。

基本クラスのポインターをベクターに保持できれば、これは非常に簡単ですが、残念ながら、私のユースケースでは、 new が配置する場所ではなく、すべてのインスタンスを連続して保存して、できるだけ多くのキャッシュヒットを取得することを非常に好みます。

私は工場マップのためにこのようなことをすることを考えていました:

Map<string,pair<constructorFnPtr, vector<baseClass>>

これには、基本クラスにキャストされるため、派生クラスからのデータが失われるという問題があります。

また、ペアの 2 番目のメンバーとしてベクトルへのポインターを使用するのも良い方法だと考えていましたが、各ベクトルに異なるデータ型を格納したまま実装する方法がわかりません。テンプレート化されたベクトルはすべて技術的に異なるクラスであるため、これは可能ではないと思います。

私がやろうとしていることをする方法はありますか?過去数日間、運が悪いので何かを理解しようとしてきました。

あるいは、ベクトルを格納する別の良い方法がある場合 (つまり、コンポーネント クラスの静的メンバーとして)、そのような提案も受け付けています!

4

2 に答える 2

2

コンポーネントにファクトリ パターンを使用することは考えませんが、代わりにエンティティの作成を管理するためにファクトリ パターンを使用する可能性が高いため、オブジェクト プール パターンを使用することを検討します。

すべてのコンポーネントに基本Componentクラスを使用します。これにより、各コンポーネントの静的ランタイム型情報を管理し、一連の共通メソッドを公開できます。IComponentPool次に、コンポーネント オブジェクト プールのコントラクトであるインターフェイスを実装しました。ComponentPool<T>次に、から派生したテンプレート化されたクラスを定義しましたIComponentPool。このテンプレート クラス内で、2 つのベクトル/配列を管理します。次に、コンポーネント タイプに基づいてComponentPoolMapをルックアップするために、いくつかのマップのような動作を公開するがあります。ComponentPool<T>

クラスComponentPool<T>では、最初の配列はルックアップとして使用されるスパース配列です。これは、2 番目の高密度パック配列内でコンポーネントが存在する場所へのインデックス オフセットを保持します。スパース配列は、単に EntityId を取得し、それをコンポーネントが存在する場所に変換する手段である可能性があります。必要に応じて、このタイプのフレームワークの上に、より洗練されたハンドル システムを簡単に実装できます。

ここでの考え方は、パックされた密集が連続したメモリ バッファーとして機能し、タイトなループでキャッシュ フレンドリーな方法で簡単に反復できるが、疎配列はコンポーネントのエンティティごとに単一レベルの間接参照を提供するというものです。

ファクトリ パターンは、エンティティEntityまたはEntityIdエンティティへのハンドルを作成し、オーク、ゾンビ、またはゲームに必要なものを構成するすべての必要な側面を作成する場所です。ファクトリは、ゲーム オブジェクト システムの最上部に位置するレイヤーとして機能しますComponentPoolMapが、そのシステムのごく一部に過ぎない可能性があります。

于 2014-10-03T02:23:54.050 に答える
0

連続したオブジェクトの std::vector ではこれを行うことはできません。

その理由は、ファクトリはオブジェクトを構築し、それらへのポインタを返すことになっているからです。your_vector.push_back()問題は、C++ のドキュメントにあるように、ポインターがアプリケーション内に保存される一方で、次の呼び出しでポインターが無効になる可能性があることです。

new size() が capacity() より大きい場合、すべての反復子と参照 (末尾反復子を含む) が無効になります。それ以外の場合は、末尾イテレータのみが無効になります。

そのため、ファクトリへの次の呼び出しで、以前のすべての呼び出しが無効になる可能性があります。

于 2014-10-01T15:20:14.797 に答える