объявить интерфейс класса obj-c, содержащий класс c ++ типа ivar - PullRequest
4 голосов
/ 18 ноября 2011

В настоящее время я работаю над проектом cocos2d + Box2D, поэтому я имею дело с некоторым кодом Objective-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.

Но если у меня есть другой файл с именем Game.m, использующий BasicNode, и импортBasicNode.h, он не будет компилироваться, поскольку файл .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) появляется только один раз.В противном случае компилятор найдет объявление нескольких типов для одного и того же имени, даже если они одинаковые.Чем мне нужно перейти на

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

И это работает сейчас.

Но я не думаю, что это хорошая идея, что я объявляю тип класса C ++ как Obj-Cособенно я использую ARC.

Есть ли лучший способ справиться с этим?И я действительно не хочу делать что-то вроде этого

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

Редактировать: Также, пожалуйста, скажите мне, будет ли мой способ настройки представить какие-либо проблемы ??делая класс C ++ ivar похожим на класс Obj-C для другого чистого кода Obj-C.

Ответы [ 3 ]

2 голосов
/ 18 ноября 2011

Одно простое решение - переименовать Game.m в Game.mm.

1 голос
/ 18 ноября 2011

Есть несколько способов.Если вы можете рассчитывать на использование функций среды выполнения Objective-C 2.2, вы можете добавить ivars в расширения класса (категории).Это означает, что вы можете добавить ivars в файл .mm вашего класса и сохранить файл .h в чистоте от любого содержимого C ++.

Если вам требуется поддержка более старых версий среды выполнения, есть несколько способов сделать это.которые лучше чем #ifdef ing.На мой взгляд, лучший способ - использовать идиому «pimpl», распространенную в C ++, - вы объявляете структуру реализации в своем заголовке и добавляете ivar, который является указателем на такую ​​структуру.В реализации вашего класса (.mm) вы фактически определяете эту структуру со всеми ее членами C ++.Затем вам просто нужно выделить этот объект реализации в ваших init... методах с new и delete в dealloc.

Я записал идиому pimpl, как она применяется кЧистое смешение Objective-C и C ++ в этой статье - оно также показывает некоторые другие потенциальные решения, которые вы могли бы рассмотреть.

0 голосов
/ 20 февраля 2014

С Xcode 5 вам не нужно объявлять переменные экземпляра в заголовочном файле, вы можете просто объявить их в файле реализации. Таким образом, ваш заголовочный файл BasicNode не «загрязнен» C ++.

Вы можете использовать "struct" вместо "class" в C ++. Единственное отличие состоит в том, что в классе все члены являются закрытыми по умолчанию, а в структуре они являются открытыми по умолчанию. Но вы можете делать все со структурой, что вы можете делать с классом. Таким образом, вы можете написать, например,

struct b2Body;
struct b2Fixture; 

вне вашего интерфейса и

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

в вашем интерфейсе.

...