c ++类循环引用?

时间:2014-05-07 13:49:22

标签: c++ lnk2005

我正在开发一个小游戏引擎,但我遇到了困难。说明:我有两个类cEntityObjectFactory

cEntity

class cEntity:public cEntityProperty
{
    Vector2 position;
    Vector2 scale;
  public:
   cEntity(void);
   cEntity(const cEntity&);
   ~cEntity(void);
  public:
   void init();
   void render();
   void update();
   void release();
};

的ObjectFactory

#include "cEntity.h"
#include <vector>

class ObjectFactory
{
   static std::vector<cEntity> *entityList;
   static int i, j;
  public:
   static void addEntity(cEntity entity) {
   entityList->push_back(entity);
}
  private:
   ObjectFactory(void);
   ~ObjectFactory(void);
};

std::vector<cEntity> *ObjectFactory::entityList = new std::vector<cEntity>();

现在我在cEnity构造函数中向ObjectFactory添加新的cEntity,但面临与循环引用相关的错误:对于使用ObjectFactor::addEntity(),我需要定义{{1}在ObjectFactory.h类中,它会创建一个循环引用。

1 个答案:

答案 0 :(得分:1)

我认为根据您描述问题的方式,您的代码可能存在潜在的架构问题。

你的ObjectFactory应该处理cEntities,而cEntities应该不知道“上面的级别”。从你所遇到的问题的描述来看,这意味着你不确定哪个班级负责什么工作。

您的cEntity应该公开一个接口(即一个类中标记为“public”的所有东西),其他代码与之交互。你的ObjectFactory(如果做这个工作有点命名,但无论如何)应该反过来使用该接口。 cEntitys不应该关心谁在使用界面:他们有一份工作要做,他们就是这样做的。 ObjectFactory应该有一个工作要求它保持一个cEntity列表。在其他地方使用它时,你不会编辑std :: string:为什么你的类有什么不同?


话虽如此,解决循环依赖关系还有两个部分(除了“首先不创建具有循环依赖关系的代码”之外) - 请参阅此答案的第一部分。这是避免此类问题的最佳方法在我看来)

1)包括警卫。对每个标题(.h)文件执行类似的操作:

#ifndef CENTITY_H
#define CENTITY_H
class cEntity:public cEntityProperty
{
Vector2 position;
Vector2 scale;
public:
cEntity(void);
cEntity(const cEntity&);
~cEntity(void);
public:
void init();
void render();
void update();
void release();
};
#endif

这是做什么的:

  • 第一次包含文件时,未定义CENTITY_H。因此ifndef宏是正确的,并且在移动到标题的其余部分之前移动到下一行(定义CENTITY_H)。
  • 第二次(以及所有将来的时间),CENTITY_H已定义,因此ifndef宏会直接跳至endif,跳过标题。随后,您的标题代码只会在您编译的程序中结束一次。如果您想了解更多详细信息,请尝试查看链接器进程的处理方式。

2)你的课程的前瞻声明。

如果ClassA需要类型为ClassB的成员,并且ClassB需要类型为ClassA的成员,则会遇到问题:两个类都不知道需要分配多少内存,因为它依赖于另一个包含自身的类。

解决方案是你有一个指向另一个类的指针。指针是编译器固定且已知的大小,因此我们没有问题。但是,我们确实需要告诉编译器如果遇到我们之前尚未定义的符号(类名),请不要太担心,所以我们只需在开始使用它之前添加class Whatever;。 / p>

在您的情况下,将cEntity实例更改为指针,并在开始时向前声明该类。您现在可以在cEntity中自由使用ObjectFactory。

#include "cEntity.h"
#include <vector>

class cEntity;  // Compiler knows that we'll totally define this later, if we haven't already

class ObjectFactory
{
static std::vector<cEntity*> *entityList;  // vector of pointers
static int i, j;
public:
static void addEntity(cEntity* entity) {  
entityList->push_back(entity);
}
// Equally valid would be:
// static void addEntity(cEntity entity) {
// entityList->push_back(&entity);}
// (in both cases, you're pushing an address onto the vector.)
// Function arguments don't matter when the class is trying to work out how big it is in memory
private:
ObjectFactory(void);
~ObjectFactory(void);
};
std::vector<cEntity*> *ObjectFactory::entityList = new std::vector<cEntity*>();