適切な質問をすることは、良い答えを得る方法の少なくとも半分です。直面している特定の問題ではなく、達成したいことを実際に述べる必要があります。私には、あなたが実際に思っている以上に言語に問題を抱えているように思えます。
最初の部分は、コンポーネントから派生したコンポーネント階層があり、おそらく共通のインターフェイスを提供しているように見えることです。エンティティは、多くのコンポーネントを内部に保持しており、Component から派生した任意の型にすることができます。その場合は、Component オブジェクトを直接格納しているため、コンテナを作り直す必要があります。これにより、オブジェクトにスライスが生成されます (コンテナに入力する派生型に関係なく、コンテナはコンポーネントの共通部分のみを保持します)。物体)。
いくつかのベクトルで作業し、両方が常に同期されることを期待することは可能ですが、脆弱です。名前とコンポーネントが一緒に使用される場合は、名前とコンポーネントのペアを保存する必要があります。名前で検索する場合は、O(log N) 検索を直接提供するため、マップを使用する必要があります。
さて、質問に戻ります。達成したいことが単純な構文糖衣である場合 (必要に応じて、呼び出し元が明示的に動的にキャストされないようにする)、テンプレートを使用してそれを取得できます (詳細は後述)。しかし、あなたは本当にあなたのデザインを考えるべきです. Component は、実際のインターフェイスをコンポーネントに定義しますか? ユーザーがコンポーネントを使用する前に特定の型にダウンキャストする必要がある場合は、抽象化が悪い (コンポーネントは実際のインターフェイスを提供しない) か、オブジェクトが実際には適合しません。
最後にまだ実行したい場合は、テンプレート メソッド (またはフリー関数) 内で実行することにより、動的キャストを呼び出し元から隠すことができます。
class Entity {
typedef std::map< std::string, boost::shared_ptr<Component> > component_map_t;
public:
boost::shared_ptr<Component> getComponent( std::string const & name ) {
component_map_t::iterator it = components_.find(name);
if ( it == components_.end() ) { // not found, handle error
// ...
}
return it->second;
}
template <typename T> // syntactic sugar
boost::shared_ptr<T> getComponent( std::string const & name ) {
return boost::dynamic_pointer_cast<T>( getComponent(name) );
}
private:
component_map_t components_;
};
template <typename T> // syntactic sugar also available as free function
boost::shared_ptr<T> getComponent( Entity & entity, std::string const & name ) {
return boost::dynamic_pointer_cast<T>( entity.getComponent(name) );
}
int main() { // usage
Entity e; // ... work with it add components...
boost::shared_ptr<Component> c1 = e.getComponent( "one" ); // non-templated method returns Component
boost::shared_ptr<DerivedComponent> c2 = e.getComponent<DerivedComponent>( "two" );
boost::shared_ptr<DerivedComponent> c3 = getComponent<DerivedComponent>( e, "two" );
}
実際の参照を返す代わりに、インターフェイスをいじることができboost::shared_ptr
ます (コンポーネントがエンティティから削除された場合に、ユーザー コードがダングリング参照を使用しないように、有効期間を慎重に制御する必要があります)。