私はC++で小さなシミュレーションフレームワークを作成しています。純粋なシミュレーション関連のものを表示から分離したいと思います。だから私は次のようなクラスを持っています:
class Pointer : public SimulationObject {};
class Particle : public SimulationObject {};
class LearningObserver : public SimulationObject {};
これらはすべてSimulationObjectから派生していますが、視覚的に表現できるのは一部(!)のみです。
class Renderable {
public:
virtual void render() const = 0;
//may also include reference to assosciated SimulationObject
}
class PointerRenderable : public Renderable {
void render() const { std::cout << "Render a pointer" << std::endl;
};
class ParticleRenderable : public Renderable {
void render() const { std::cout << "Render a particle" << std::endl;
};
これで、新しいSimulationObjectが(実行時に)シミュレーションに追加されるたびに、それをレンダリングするクラスがあるかどうかを確認したいと思います。もしそうなら、私はそれのインスタンスを作成したいと思います。私の最初のアイデアは、ポリモーフィを使用することでした。
class AbstractRenderFactory {
virtual Renderable * provideRenderable(SimulationObject * so) const = 0;
};
class ConcreteRenderFactory {
void PointerRenderable * provideRenderable(Pointer * pointer) {
return new PointerRenderable();
}
// further provideRenderable's
};
ただし、メソッドをオーバーライドするときに派生型を使用することは明らかに機能しません(基本メソッドが呼び出されます)。また、関数は部分的にしか定義されないため、これには問題があります。
別のアイデアは、タイプの実際のマッピングを提供することでした。
std::map<std::type_index, std::type_index> renderTable;
しかし、type_infoを使用するだけではインスタンスを取得できません。アイデアはありますか?
更新:ビジターパターンを使用してみましたが、同様の問題が発生しました。私の訪問者クラスは次のようになります。
class RenderVisitor {
public:
virtual Renderable * visit(SimulationObject * so) {
// I would like to have this method abstract, but I could live with this
return 0;
}
};
class MyRenderVisitor : public RenderVisitor {
public:
Renderable * visit(Pointer * pointer) const {
return new PointerRenderable();
}
};
さらに、シミュレーションパーツの新しい基本クラス。
class SimulationObject {
public:
Renderable * accept(RenderVisitor * renderer) {
return renderer->visit(this);
}
};
MyRenderVisitorのvisit-methodは明らかに基本クラスのオーバーライドとして認識されませんが、これが実際の(派生)タイプを指しているので、正しいメソッド(MyRenderVisitorのメソッド)が呼び出されることを期待していました。
私のテストシナリオは次のようになります。
RenderVisitor * rv = new MyRenderVisitor();
SimulationObject * pointer = new Pointer();
Renderable * renderable = pointer->accept(rv);
renderable->render();
// renderable = 0 -> seg-fault
それとも私の実装が間違っているだけですか?