1

对于我正在编写的程序,我在 C++ 中拥有一个充满动物实体的 2d 世界。我有一个世界级和实体类(以及从实体继承的一系列不同类型的实体)。

我希望实体“知道”它所在的世界并能够与二维实体数组很好地交互,但我不希望它从世界继承(毕竟,实体不是世界)。所以我只是想获得一些想法来实现这个的好方法。我当然可以让每个实体都包含一个指向它所在世界的指针,但它看起来相当混乱。二维数组中的实体是否有更简单的方法来“知道”哪个世界对象包含它。

c++ 中有没有办法让一个对象作为另一个对象的成员变量知道包含它的对象?

谢谢!

4

4 回答 4

3

聚合(为每个实体提供一个世界指针)是最简单的解决方案。另一种解决方案是使用第三个中介对象,它维护指向世界和实体的指针,存储它们的关系,并调解(因此得名)它们之间的通信。这个对象可能是一个全局单例(大多数程序员会不寒而栗,但我不认为其中一些是坏事),或者每个世界和实体都需要一个指向的指针来进行通信,这显然不是一个大问题对第一个解决方案的改进。

于 2013-05-15T16:16:21.660 回答
1

我有世界级的

哦亲爱的。


除此之外,您的实体与其环境的有意义的交互是什么?它是否应该能够查询任意信息、查看地平线、询问其他实体的状态?

或者它应该有一些有限的视野,基于它的位置和属性?

在第一种情况下,它显然是一个神一般的实体,不适用诸如封装和关注点分离之类的普通关注点。

在第二种情况下,公开一个接口(您可以将其抽象化以减少耦合),使其只看到它应该看到的内容。


好的,所以第二种情况可能看起来像

class World; // is a dumb container of entities
class Environment; // is an entity's window on the world
class Entity {
public:
    void take_a_turn(Environment&) = 0;
};
class Environment {
public: // control what an entity can do to (see of) the World
    container<const Entity*> visible_entities() const;
    result attempt_to_eat(const Entity*);
    result attempt_to_mate(const Entity*);
    result run_away_from(const Entity*);
};

当然,如果您的 Entity 对象是活动的(即,它们在自己的线程中自主且连续地运行),它们需要保持对世界或环境的引用或指针。

但是,如果您只是一次调用它们,当它们有机会做某事时,每次传递引用都可以。

于 2013-05-15T16:14:11.547 回答
1

假设我对您的理解正确,每个实体中的世界指针的替代方法是给每个世界一个唯一的 id,然后将该 id 存储在实体中,因为它被添加到它的世界中。

于 2013-05-15T16:15:22.947 回答
0

对于世界,也许您可​​以创建某种全球引擎。引擎将有系统,世界可以被认为是引擎内部的系统。您将在实体的构造函数中向引擎请求世界系统,并在其中执行您需要的操作。

class World : public System
{
  // info in here
}


class Engine 
{
  public:
    World * getWorldSystem(); // Not as good
    System * getSystem( std::string name ); // uses lookup, convert to right type

}

引擎类的问题是“我如何引用它?” 在大多数情况下,您将包含引擎的 .h 文件,该文件还具有:

extern Engine * ENGINE;

在其中,我理解这很可怕,但是对于引擎/系统架构,您必须在某个地方拥有它。或者您明确使用单例。

至于你的继承树可能会完全改变你的设计方案。基于组件的架构可能是您解决此问题的一种方式。

虽然继承在很多情况下都是有意义的,但构建基于组件的实体将帮助您处理每只动物必须拥有的大量奇怪类型。

拿:

class Component
{
  public:
    Component();
    virtual ~Component();

}

class WalkComponent : public Component
{
  public:
    Walk(); // Something here allows the entity to walk on the ground
}

class FlightComponent : public Component
{
  public:
    Fly(); // Something in here moves the entity around using flight
}

马上你可以看到你可以将一个 walk 组件和一个 flight 组件附加到实体上,它会同时拥有这两者,而不是尝试创建一个允许这两者的继承树。

于 2013-05-15T16:21:36.797 回答