循环依赖难题

时间:2013-08-01 10:31:48

标签: c++ circular-dependency

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

Renderer的实例呈现Object的实例。但是Object的实例会将自己添加或从要呈现的事物列表中删除。

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

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

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

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

修改 为了更清晰,我重写了我的问题,并将第二部分移到了一个新的问题,它可能更具相关性,并避免在这里进一步混淆。

2 个答案:

答案 0 :(得分:0)

不确定我是否真的理解这个意图。但是,我想重温你原来的问题:

  

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

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

class Object;
class Renderer;
class Engine;

虽然更清洁的是使用Interface类。

修改 我是否理解正确,问题是你想将Rendered实例传递给Object,所以对象可以使用渲染器绘制自己?

然后接口类怎么样:

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

class Object : public Paintable
{
    ...
}

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

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

答案 1 :(得分: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;
}