仮想関数を定義するBaseという基本クラスがあります。Derivedクラスはそれを継承し、その仮想関数を実装/上書きします。次のコードは問題なく機能します。
Base* pB = new Derived();
pB->virtual_function(); // function of class Derived gets called -> good
私の問題は、すべての派生インスタンスをSTLコンテナに格納することstd::map<ID, Base*>
です。後でそのコンテナを繰り返し処理し、各Base *で仮想関数を呼び出そうとすると、ランタイムはポインタをBase *型としてのみ認識し、 Derivedクラスのオーバーライドされた実装を呼び出さないため、これは問題を引き起こすようです。
それを意図したとおりに機能させる方法はありますか、それともここで重要なポイントを見逃していますか?
編集1:いくつかの追加コードが要求されたので、ここに行きます:
std::map<ComponentType, Base*> m_Components;
// The factory instantiates a Derived* (via functors) and returns it as Base*
Base* pB = m_pComponentFactory->createComponent(this, type);
// Lazy insert (since there is no map entry with key 'type' at that stage)
m_Components[type] = pB;
[...]
Base* pB;
for(ComponentMap::const_iterator it = m_Components.begin(); it != m_Components.end( ); ++it)
{
pB = it->second;
pB->virtual_function(); // goes to Base instead of Derived
}
編集2:私が今気づいたことの1つは dynamic_cast
、ファンクターを介してDerivedインスタンスを作成した後、呼び出し(または同様のもの)しないことです(ただし、すべて汎用/動的であるため、とにかく何にキャストするかわかりません)。return creator()
クリエーターがファンクターであるだけです。それが問題ですか?
クリエータータイプ(ファンクトンタイプ)の定義:
typedef Base*(*ComponentCreator)([some params]);
編集3: 実際のファンクターは、たとえば次のように定義されます(RenderableとLocationはBaseから派生したクラスです)。
&Renderable::Create<Renderable> // or
&Location::Create<Location>
Create()メソッドは、クラスBaseのテンプレート関数です。
template<typename T>
static Component* Create([some params])
{
return new T([some params]);
}
編集4: 問題は私のclone()+CopyConstructorの処理にあるようです。私のクローンは現在次のようになっています:
Base* Base::clone() const
{
return new Base(*this);
}
Base *のみを作成しているため、後で仮想解像度を作成することはできません。しかし、私が今残している問題は、クローンを変更する方法がわからないことです。EDIT 1に示されているようにm_Components
、Base*ポインターを使用したマップがあります。今、それらのクローンを作成する必要がありますが、それらがBase *のものであり、正確な派生物ではないことだけを知っています。頭に浮かぶアイデアの1つは、Derivedインスタンスを作成するために使用したファンクターをクラスの最初の場所に格納し、後で再利用することです。したがって、私のクローンは次のようになります。
Base* Component::clone() const
{
return m_pCreationFunctor([some params]);
}
より良いアプローチを見ている人はいますか?