我正在开发一个小游戏引擎,但我遇到了困难。说明:我有两个类cEntity
和ObjectFactory
:
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();
};
#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
类中,它会创建一个循环引用。
答案 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
这是做什么的:
ifndef
宏是正确的,并且在移动到标题的其余部分之前移动到下一行(定义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*>();