我正在使用名为Bullet的物理库,但我无法阻止将Bullet标题包含在我的物理标题中。
//Physics.h
#include <BulletPhysics/btBulletDynamicsCommon.h> // Contains lots of other headers
struct Physics
{
static btDiscreteDynamicsWorld* pDynamicsWorld;
static btAlignedObjectArray<btCollisionShape*> collisionShapes;
static vec3 findSomePoint();
};
现在在我的代码的其他各个部分中,我可能想要访问Physics结构,为此我需要包含Physics标头,但这也将包括任何其他CPP文件中的所有库标头。
我正在试图找到一种方法让图书馆标题只包含在Physics.cpp中,但如果我从Physics.h中删除标题,我就无法让编译器识别结构定义中的库类型
对于一些成员,我可以直接声明并且工作正常,但它不适用于非指针或引用类型,因为需要完整定义。
我注意到如果我使用命名空间,我可以将成员声明为extern,并且不需要完整的类型定义。但是它会在前向声明中产生奇怪的结果:
struct btDiscreteDynamicsWorld; // This seems fine
template <typename T>
struct btAlignedObjectArray; // This works but seems really hacky and I'm not sure if it's even valid
namespace Physics
{
extern btDiscreteDynamicsWorld* pDynamicsWorld;
extern btAlignedObjectArray<btCollisionShape*> collisionShapes; // Complete type not needed
vec3 findSomePoint();
}
同样使用命名空间我失去了使用访问说明符的能力。
我还想过,不是在结构中有成员本身,我可以使用getter函数并返回引用,但返回类型也至少需要一个前向声明(我认为不完整的类型),我仍然需要转发以我之前的方式声明该模板类型。
这是最好的方法吗?或者我过分强调防止复制额外的标题。那一个标题包含许多其他标题,所以它非常多,所以我不确定我是否应该关心。
答案 0 :(得分:0)
这两个构造具有相似的含义,除了第二个构造允许您选择创建和启动内存的位置。我个人不会太担心递归阅读器内容,你投射的项目是非常大的。您实际上在这里使用全局变量来获得一些非常重要的共享状态,这通常表示您的设计中的流程。如果您的程序是多线程的,并且无法绕过共享状态,
我建议使用第三种方法并在getter和setter中执行一些互斥(读者 - 服务员锁似乎合适)在这种情况下,您需要确保状态仅通过setter进行修改(可能通过返回来自getter的const引用。
如果您要坚持使用extern
解决方案并在非平凡中初始化这些对象(我假设它不是),您还需要定义某种初始化函数并确保调用它在其他任何事情之前,在这种情况下你应该考虑编写一个Singleton类,这就是我要做的。