Declare an obj-c class interface that contains the c ++ type of the ivar class

I am currently working on a cocos2d + Box2D project, so I am dealing with some Objective-C ++ code.

And I came across a situation like this:

#import "cocos2d.h" #import "Box2D.h" @interface BasicNode : CCNode { @private ccColor3B _color; b2Body *_body; b2Fixture *_shape; } 

b2Body and b2Fixture are the C ++ class defined in Box2D.h

It works if the implementation of BasicNode is called BasicNode.mm.

But if I have another file called Game.m that uses BasicNode and imports BasicNode.h, it will not compile because the .m file is an Obj-C file and does not know about C ++ code.

So, I decided to move #import "Box2D.h" to the implementation file and only save the type declaration in the head file (this is exactly what the header file should contain).

But how do I do this? This is a C ++ class type, but they are actually just a pointer, so I wrote some helper macros

 #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); 

It only works if CLS_DEF (b2Body) appears only once. Otherwise, the compiler will find several type declarations for the same name, even if they are the same. What should I switch to

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

And now it works.

But I don’t think it’s a great idea that I declare a C ++ class type as an Obj-C class, especially using ARC.

Is there a better way to handle this? And I really don't want to do something like this

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

Edit: Also, please tell me if my setup method will be any problem? by creating a C ++ class, the ivar class looks like the Obj-C class for other pure Obj-C code.

+4
source share
3 answers

There are several ways. If you can rely on the use of Objective-C 2.2 runtime functions, you can add ivars to class (category) extensions. This means that you can add ivars to your .mm file and save the .h file in any C ++ material.

If you need to support older versions of the runtime, there are several ways to do this, which are better than #ifdef ing. In my opinion, the best way is to use the "pimpl" idiom, which is common in C ++, - you transfer the declaration of the implementation structure to your header and add ivar, which is a pointer to such a structure. In the implementation of your class (.mm), you actually define this structure with all its C ++ members. Then you just need to highlight this implementation object in the init... method with new and delete in dealloc .

I wrote the pimpl idiom as it applies to purely mixing Objective-C and C ++ in this article - it also shows some other potential solutions that you might consider.

+1
source

One simple solution is to rename Game.m to Game.mm

+2
source

With Xcode 5, you do not need to declare instance variables in the header file, you can simply declare them in the implementation file. Therefore, your BasicNode header file is not "infected" with C ++.

You can use "struct" instead of "class" in C ++. The only difference is that in the class all members are private by default, and in the structure they are public by default. But you can do everything with a structure that you can do with a class. So you can write for example

 struct b2Body; struct b2Fixture; 

outside your interface and

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

in your interface.

0
source

Source: https://habr.com/ru/post/1381876/


All Articles