1

私の C++ プロジェクトには、Engineクラス、Rendererクラス、Objectクラスがあります。

のインスタンスは のインスタンスをRendererレンダリングしますObject。ただしObject、レンダリングする対象のリストから自分自身を追加したり、自分自身を削除したりするインスタンス。

使いやすさの観点から、 のインスタンスがObjectから描画されるかどうかを設定できる必要がありますObjectが、循環依存関係はありません。

この問題の解決策はありますが、それが良いアイデアかどうかはわかりません:

ゲーム内の更新サイクルは、すべてのオブジェクトの関数を呼び出すクラスUpdate()内の関数によって行われます。の各インスタンスに対して関数を呼び出す場合、クラス内の 2 つのブール変数をチェックするように設定できます。1 つは描画すべきかどうか、もう 1 つは実際に描画されているかどうかです。したがって、これにより、必要に応じてレンダリング対象のリストに のインスタンスを追加または削除できるようになります。EngineUpdate()Update()ObjectObjectObject

このようにするのは良い考えですか?この方法は効率的ですか、それとも循環依存関係のないより良い方法はありますか?

編集: より明確にするために質問を書き直し、2番目の部分をおそらくより関連性の高い新しい質問に移動し、ここでさらに混乱を避けるようにしました。

4

2 に答える 2

0

Object は Rendered から継承し、Renderer は Object ではなく Rendered のみを認識する必要があります (以下を参照)。

#include <iostream>
#include <list>

struct Renderer;

struct Rendered
{
    virtual void renderMe( Renderer& ) = 0;
  protected:
    //Renderer won't delete me...
    virtual ~Rendered(){}
};

struct Object : Rendered
{
  virtual void renderMe( Renderer& )
  {
    std::cout << "I'm rendered!" << std::endl;
  }
};

struct Renderer
{
  void add( Rendered& r )
  {
    renderList_.push_back( & r );
  }
  void remove( Rendered& r );//...use your imagination

  void render()
  {
    for( std::list<Rendered*>::iterator i = renderList_.begin(); i != renderList_.end(); ++i )
    {
      (*i)->renderMe( *this );
    }
  }
  private:
    std::list<Rendered*> renderList_;
};

struct Engine
{
  Renderer& renderer_;
  Object myObject_;
  Engine( Renderer& r )
  : renderer_( r )
  {
    renderer_.add( myObject_ );
  }
  ~Engine()
  {
    renderer_.remove( myObject_ );
  }
};

int test()
{
  Renderer r;
  Enginer e( r );
  r.render();
  return 0;
}
于 2013-08-01T12:03:39.637 に答える
0

意図を本当に理解しているかどうかはわかりません。ただし、元の質問を再検討したいと思います。

現在、Object のインスタンスを描画するには、Renderer の描画するオブジェクトのリストのインスタンスにそれ自体を追加する必要があります。これは、Renderer のインスタンスへのポインターが必要であることを意味しますが、Renderer はオブジェクトを描画するために Object についても知る必要があります。

なぜこれが問題なのですか?ポインタだけが必要な場合は、クラス タイプを前もって宣言できます。

class Object;
class Renderer;
class Engine;

ただし、よりクリーンなインターフェイス クラスを使用することもできます。

編集: 私は正しく理解していますか?問題は、レンダリングされたインスタンスをオブジェクトに渡したいということです。そのため、オブジェクトはレンダラーを使用して自分自身をペイントできますか?

では、Interface クラスはどうなるでしょうか。

class Paintable
{
    public:
        virtual void paint(Renderer *) = 0;
};

class Object : public Paintable
{
    ...
}

ペイント可能なオブジェクトはすべてインターフェイスから拡張されます。このように、Renderer クラスはオブジェクトのベクトルを保持する必要はありませんが、Paintable へのポインターのベクトルを保持する必要があります。(例: Renderer は Object に依存しなくなりました)

回答: 2 番目のコメントへ 選択肢があるかどうかわかりません。オブジェクトの内部データ (色、位置など) および Renderer ハンドルにアクセスするには、レンダリング コードが必要です。オブジェクトの内部データにアクセスする Renderer のコードを選択できます。これは悪い考えだと思います。Renderer は、さまざまなオブジェクトを処理するさまざまなコードを必要とし、場合によってはオブジェクトのプライベート メンバーにもアクセスする必要があるからです。もう 1 つの方法は、Renderer ハンドルを指定して自分自身をレンダリングできるインテリジェント オブジェクトを用意することです。したがって、renderer.paintLine(...) などを呼び出すことができます。Renderer は保持するオブジェクトについての知識を必要としないため、Interface クラスの使用は適切です。

于 2013-08-01T11:08:04.527 に答える