简体   繁体   English

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

[英]How to prevent including header in header to minimise including in other CPPs

I'm using a physics library called Bullet and I'm having trouble preventing including the Bullet headers into my Physics header. 我正在使用一个名为Bullet的物理库,但无法阻止将Bullet标头包含在Physics标头中。

//Physics.h
#include <BulletPhysics/btBulletDynamicsCommon.h> // Contains lots of other headers

struct Physics
{
    static btDiscreteDynamicsWorld* pDynamicsWorld;
    static btAlignedObjectArray<btCollisionShape*> collisionShapes;
    static vec3 findSomePoint();
};

Now in various other parts of my code I may want to access the Physics struct, and to do this I need to include the Physics header, but that will also include all the library headers in any other CPP file. 现在,在代码的其他各个部分中,我可能想要访问Physics结构,并且为此,我需要包括Physics标头,但是这还将包括所有其他CPP文件中的所有库标头。

I'm trying to figure a way to have the library headers only included in Physics.cpp, but I'm having trouble getting the compiler to recognise the library types in the struct definition if I remove the header from Physics.h. 我试图找到一种仅在Physics.cpp中包含库标头的方法,但是如果我从Physics.h中删除标头,则很难使编译器识别结构定义中的库类型。

With some of the members I can just forward declare and that works fine, but it's not going to work for non pointer or reference types as the full definition is needed. 对于某些成员,我可以只进行正向声明,并且可以正常工作,但不适用于非指针或引用类型,因为需要完整的定义。

I noticed that if I use a namespace I can get away with declaring a member as extern, and the full type definition isn't needed. 我注意到,如果使用命名空间,则可以将成员声明为extern,而不必使用完整的类型定义。 But it results in weird things with the forward declarations: 但是,使用前向声明会导致一些奇怪的事情:

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();
}

Also using a namespace I lose the ability to use access specifiers. 同样使用命名空间,我也失去了使用访问说明符的能力。

I also thought instead of having the members themselves in the struct I could use getter functions and return references, but the return types also need at least a forward declaration (not complete type I think), and I would still have to forward declare that template type the way I did earlier. 我还认为,可以使用getter函数和返回引用来代替将成员本身包含在结构中,但是返回类型还至少需要一个前向声明(我认为不是完整的类型),并且我仍然必须前向声明该模板输入我之前的方式。

Which is the best way to do this? 哪个是最好的方法? Or am I placing too much emphasis on preventing the copying of extra headers. 还是我过于强调防止复制多余的标题。 That one header contains many many other headers, so it is quite a lot, so I'm not sure if I should care or not. 一个标头包含许多其他标头,因此数量很多,因此我不确定是否应该关心。

These two constructs have similar meaning, except that the second one allows you to choose where the memory is created and initilized. 这两个构造具有相似的含义,不同之处在于第二个构造允许您选择在何处创建和初始化内存。 I personally would not worry too much aout recursive reader inclusions lues you project is quite big. 我个人不会担心过多的递归阅读器内容会导致您的项目很大。 You are essentially using global variables here for some quite significant shared state, which usually indicates a flow in your design. 实际上,您在这里使用全局变量来实现一些相当重要的共享状态,这通常表明设计中存在流程。 If your program is multi-threaded and there is no way around the shared state, 如果您的程序是多线程的,并且无法解决共享状态,

I suggest using the third approach and perform some mutual exclusion in the getters and setters (readers-waiter lock seems appropriate) in which case you would need to ensure somehow that the state is only modified through the setter (probably by returning a const reference from the getter. 我建议使用第三种方法,并在getter和setter中执行一些互斥(readers-waiter锁似乎是适当的),在这种情况下,您将需要确保以某种方式仅通过setter修改状态(可能是通过返回const引用)吸气剂。

If you were going to stick with the extern solution and initialisation of these objects in non-trivial (which I assume it is not) you also want to define some sort of initialiser function and make sure that gets called before anything else, in which case you should probably consider writing a Singleton class instead, which is what I would do. 如果您要坚持使用extern解决方案并以非平凡的方式初始化这些对象(我认为并非如此),则还需要定义某种初始化函数,并确保在其他任何事情之前先调用它您应该考虑改写Singleton类,这就是我要做的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM