1

在我的 C++ 项目中,我有一个Engine类,一个Renderer类和一个Object类。

的实例Renderer呈现 的实例ObjectObject然而,添加自己或从要渲染的事物列表中删除自己的实例。

从可用性的角度来看,应该可以设置 的实例是否Object从 中绘制Object,但没有循环依赖。

我对这个问题有一个可能的解决方案,但我不知道这是否是个好主意:

游戏中的更新周期是通过类中Update()的一个函数来完成的,该函数为每个对象Engine调用函数。在为 的每个实例Update()调用函数时,我可以将其设置为检查类中的两个布尔变量。一是是否应该绘制,一是是否实际绘制。因此,这应该允许根据需要从要渲染的事物列表中添加或删除 的实例。Update()ObjectObjectObject

这样做是个好主意吗?这种方式有效还是没有循环依赖的更好方式?

编辑: 为了更清楚起见,我重写了我的问题,并将第二部分移到了一个可能更相关的新问题,并避免在这里进一步混淆。

4

2 回答 2

0

不确定我是否真的理解意图。但是,我想重新审视你原来的问题:

目前,为了绘制 Object 的实例,它需要将自己添加到 Renderer 的要绘制的对象列表的实例中。这意味着它需要一个指向 Renderer 实例的指针,但是 Renderer 还需要知道 Object 才能绘制它。

为什么这是个问题?如果你只需要指针,你可以预先声明类类型:

class Object;
class Renderer;
class Engine;

虽然,更清洁的人会使用接口类。

编辑: 我理解正确吗,问题是您想将渲染实例传递给对象,以便对象可以使用渲染器绘制自己?

那么接口类呢:

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

class Object : public Paintable
{
    ...
}

您所有的可绘制对象都将从界面扩展。这样,Renderer 类就不需要保存对象的向量,而是保存指向 Paintable 的指针向量。(例如渲染器不再依赖于对象)

答案:第二条评论不确定您是否有选择。您需要渲染代码段来访问对象的内部数据(颜色、位置等...)和渲染器句柄。您的选择是让渲染器中的代码访问对象的内部数据。我认为这是一个坏主意,因为渲染器需要不同的代码来处理不同的对象,并且还可能访问对象的私有成员。另一种方法是让智能对象可以在给定渲染器句柄的情况下渲染自己。所以他们可以调用:renderer.paintLine(...) 等。使用 Interface 类很简洁,因为 Renderer 不需要了解它所拥有的对象。

于 2013-08-01T11:08:04.527 回答
0

您可能希望 Object 从 Rendered 继承,并且 Renderer 只知道 Rendered,而不是 Object(见下文):

#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 回答