4

現在、私はcocos2d + Box2Dプロジェクトに取り組んでいるので、いくつかのObjective-C++コードを扱っています。

そして、私はそのような状況に直面しています:

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

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

b2Bodyとb2Fixtureは、Box2D.hで定義されたC++クラスです。

BasicNodeの実装の名前がBasicNode.mmの場合に機能します。

しかし、BasicNodeを使用してBasicNode.hをインポートするGame.mという名前の別のファイルがある場合、.mファイルはObj-Cファイルであり、C ++コードを認識していないため、コンパイルされません。

そこで、#import "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)が1回だけ表示される場合にのみ機能します。そうしないと、コンパイラは、同じ名前であっても、同じ名前の複数の型宣言を検出します。私が変更する必要があるより

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

そして、それは現在機能しています。

しかし、特にARCを使用している場合、C++クラス型をObj-Cクラスとして宣言するのは良い考えではないと思います。

それに対処するためのより良い方法はありますか?そして、私は本当にこのようなものを作りたくありません

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

編集:また、私の微調整方法で問題が発生するかどうか教えてください?? C ++クラスを作成することにより、ivarは他の純粋なObj-CコードのObj-Cクラスのように見えます。

4

3 に答える 3

2

簡単な解決策の1つは、名前をに変更するGame.mことGame.mmです。

于 2011-11-18T10:42:46.500 に答える
1

いくつかの方法があります。Objective-C 2.2ランタイムの機能の使用に依存できる場合は、クラス(カテゴリ)拡張機能にivarを追加できます。これは、クラスの.mmファイルにivarを追加し、.hファイルからC++のものをクリーンに保つことができることを意味します。

#ifdef古いバージョンのランタイムをサポートする必要がある場合は、 ingよりも優れた方法がいくつかあります。私の意見では、最良の方法は、C++で一般的な「pimpl」イディオムを使用することです。ヘッダーで実装構造体を前方宣言し、そのような構造体へのポインターであるivarを追加します。クラスの実装(.mm)では、実際にその構造体をすべてのC++メンバーで定義します。次に、その実装オブジェクトをinit...メソッドに割り当てnewdeleteそれをで割り当てる必要がありますdealloc

この記事では、Objective-CとC ++をきれいに混合するために適用される単純なイディオムを作成しました。これは、検討できる他のいくつかの潜在的な解決策も示しています。

于 2011-11-18T11:21:44.377 に答える
0

Xcode 5では、ヘッダーファイルでインスタンス変数を宣言する必要はありません。実装ファイルで宣言するだけです。したがって、BasicNodeヘッダーファイルはC++で「汚染」されていません。

C++では「class」の代わりに「struct」を使用できます。唯一の違いは、クラスではすべてのメンバーがデフォルトでプライベートであるのに対し、構造体ではデフォルトでパブリックであるということです。ただし、クラスで実行できる構造体ですべてを実行できます。そうすれば、たとえば書くことができます

struct b2Body;
struct b2Fixture; 

インターフェイスの外、および

{ ...
    struct b2Body* _body;
  ...
}

あなたのインターフェースで。

于 2014-02-19T22:03:27.807 に答える