![](/img/trans.png)
[英]Repeated Multiple Definition Errors from including same header in multiple cpps
[英]How to prevent including header in header to minimise including in other CPPs
我正在使用一個名為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();
};
現在,在代碼的其他各個部分中,我可能想要訪問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函數和返回引用來代替將成員本身包含在結構中,但是返回類型還至少需要一個前向聲明(我認為不是完整的類型),並且我仍然必須前向聲明該模板輸入我之前的方式。
哪個是最好的方法? 還是我過於強調防止復制多余的標題。 一個標頭包含許多其他標頭,因此數量很多,因此我不確定是否應該關心。
這兩個構造具有相似的含義,不同之處在於第二個構造允許您選擇在何處創建和初始化內存。 我個人不會擔心過多的遞歸閱讀器內容會導致您的項目很大。 實際上,您在這里使用全局變量來實現一些相當重要的共享狀態,這通常表明設計中存在流程。 如果您的程序是多線程的,並且無法解決共享狀態,
我建議使用第三種方法,並在getter和setter中執行一些互斥(readers-waiter鎖似乎是適當的),在這種情況下,您將需要確保以某種方式僅通過setter修改狀態(可能是通過返回const引用)吸氣劑。
如果您要堅持使用extern
解決方案並以非平凡的方式初始化這些對象(我認為並非如此),則還需要定義某種初始化函數,並確保在其他任何事情之前先調用它您應該考慮改寫Singleton類,這就是我要做的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.