简体   繁体   中英

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.

//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.

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.

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. 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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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