2011-11-18 57 views
4

目前我正在研究cocos2d + Box2D項目,因此我已經處理了一些Objective-C++代碼。聲明包含C++類型ivar的obj-c類接口

而且我現在面臨這樣的局面:

#import "cocos2d.h" 
#import "Box2D.h" 

@interface BasicNode : CCNode { 
@private 
    ccColor3B _color; 
    b2Body *_body; 
    b2Fixture *_shape; 
} 

b2Body和b2Fixture是C,在Box2D.h

它的工作原理,如果BasicNode實施名爲BasicNode.mm定義++類。

但是,如果我有一個使用BasicNode和進口BasicNode.h名爲Game.m另一個文件,它不會編譯,因爲.m文件爲對象 - 文件,不知道C++代碼。

所以我決定搬到#進口「Box2D.h」爲實現文件只保留在頭文件類型聲明(這恰恰是頭文件應包含)。

但我該怎麼做呢?他們是C++類的類型,但它們實際上只是一個指針所以我寫了一些輔助宏

#ifdef __cplusplus 
#define CLS_DEF(clsname) class clsname 
#else 
#define CLS_DEF(clsname) struct clsname; typedef struct clsname clsname 
#endif 

CLS_DEF(b2Body); 
CLS_DEF(b2Fixture); 

它的工作原理,只有當CLS_DEF(b2Body)是唯一的一次出現。否則,編譯器會爲同一個名稱查找多個類型聲明,即使它們是相同的。比我必須改成

#ifdef __cplusplus 
#define CLS_DEF(clsname) class clsname 
#else 
#define CLS_DEF(clsname) @class clsname 
#endif 

它現在正在工作。

但我不認爲這是我宣佈一個C++類類型作爲對象 - 類特別是我使用ARC一個偉大的想法。

是否有更好的方法來處理它?我真的不希望做這樣的事情

@interface BasicNode : CCNode { 
@private 
    ccColor3B _color; 
#ifdef __cplusplus 
    b2Body *_body; 
    b2Fixture *_shape; 
#else 
    void *_body; 
    void *_shape; 
#endif 
} 

編輯:也請告訴我,我會TWEAK方式引入任何問題?通過使C++類ivar看起來像其他純粹Obj-C代碼的Obj-C類。

回答

1

有幾種方法。如果您可以依賴於使用Objective-C 2.2運行時的功能,則可以在類(類別)擴展中添加ivars。這意味着你可以在你的類的.mm文件中添加ivars,並保持.h文件清理任何C++的東西。

如果您需要支持舊版本的運行時,有幾個方法可以做到這一點它比#ifdef ING更好。在我看來,最好的方法是使用C++中常見的'pimpl'成語 - 你在頭部聲明一個實現結構,並添加一個指向這樣的結構的指針。在你的類的實現(.mm)中,你實際上是用它的所有C++成員定義了這個結構體。然後,您只需在方法中使用newdelete分配該實現對象,然後在dealloc中分配該實現對象。

我已經寫了pimpl成語,因爲它適用於乾淨地混合Objective-C和C++在this article - 它也顯示了一些其他可能的解決方案,你可以考慮。

+0

看起來不錯,除了C++類型成員沒有更多合成屬性。如果不引入新問題,我仍然更喜歡我的調整方式。 –

+0

您仍然可以合成PIMPL類型的屬性。將指向C++對象的指針作爲指向Obj-C類的指針看起來是個不錯的主意,但只要您不使用ARC,您可能就沒問題。 – pmdj

2

一個簡單的解決方案是重命名Game.mGame.mm

+0

是的,它會。我只需要記住將每個.m文件改爲.mm文件。 –

+0

確切地說,一旦使用C++頭文件,它可能會「傳播」到其他類中,所以最好將.mm作爲所有ObjC類的默認擴展名。 – LearnCocos2D

+1

請注意,包含C++頭文件「無處不在」可能會減慢編譯速度。取決於項目的規模,頭文件的複雜性(STL,boost和類似的最差)以及計算機的速度。 – pmdj

0

使用Xcode 5,您不必在頭文件中聲明實例變量,只需在實現文件中聲明它們即可。所以你的BasicNode頭文件不會被C++「污染」。

您可以在C++中使用「struct」而不是「class」。唯一的區別是,在一個類中,所有成員默認都是私有的,而在一個結構中它們默認是公共的。但是你可以用一個你可以用一個類來完成的結構來做所有事情。這樣,你可以例如

struct b2Body; 
struct b2Fixture; 

你的界面之外編寫,並

{ ... 
    struct b2Body* _body; 
    ... 
} 
在你的界面