在我的C ++项目中,我有一个Engine
类,一个Renderer
类和一个Object
类。
Renderer
的实例呈现Object
的实例。但是Object
的实例会将自己添加或从要呈现的事物列表中删除。
从可用性的角度来看,应该可以设置是否从Object
中绘制Object
的实例,但没有循环依赖。
我有一个可能解决这个问题的方法,但我不知道这是不是一个好主意:
游戏中的更新周期是通过Update()
类中的Engine
函数完成的,该函数为每个对象调用Update()
函数。当为Update()
的每个实例调用Object
函数时,我可以将其设置为检查Object
类中的两个布尔变量。一,是否应该绘制,一个是否实际绘制。因此,这应允许在要根据需要呈现的事物列表中添加或删除Object
的实例。
这样做是不是一个好主意?这种方式有效还是没有循环依赖的更好方法?
修改 为了更清晰,我重写了我的问题,并将第二部分移到了一个新的问题,它可能更具相关性,并避免在这里进一步混淆。
答案 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;
}