如何防止在标题中包含标题以最小化包含在其他CPP中

时间:2018-01-05 08:44:44

标签: c++ header definition code-separation

我正在使用名为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函数并返回引用,但返回类型也至少需要一个前向声明(我认为不完整的类型),我仍然需要转发以我之前的方式声明该模板类型。

这是最好的方法吗?或者我过分强调防止复制额外的标题。那一个标题包含许多其他标题,所以它非常多,所以我不确定我是否应该关心。

1 个答案:

答案 0 :(得分:0)

这两个构造具有相似的含义,除了第二个构造允许您选择创建和启动内存的位置。我个人不会太担心递归阅读器内容,你投射的项目是非常大的。您实际上在这里使用全局变量来获得一些非常重要的共享状态,这通常表示您的设计中的流程。如果您的程序是多线程的,并且无法绕过共享状态,

我建议使用第三种方法并在getter和setter中执行一些互斥(读者 - 服务员锁似乎合适)在这种情况下,您需要确保状态仅通过setter进行修改(可能通过返回来自getter的const引用。

如果您要坚持使用extern解决方案并在非平凡中初始化这些对象(我假设它不是),您还需要定义某种初始化函数并确保调用它在其他任何事情之前,在这种情况下你应该考虑编写一个Singleton类,这就是我要做的。