Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recommended way to use C++ class into Objective-C class minimizing using of Objective-C++?

I'm mixing Objective-C and C++. However I want to minimize using of Objective-C++. Because it has some kind of limits in both of Objective-C and C++.

Currently, I'm using it like this.

// A.h, Objective-C
#import "B.h"
@interface A
{
    B* b;
}
@end

// B.h, Objective-C++
@interface B
{
    void* c;
}

// C.h, C++
class C
{
};

I want to include C.h in B.h, but if I did it, B.h cannot be imported into A.h. So I have to leave variable c as void* type. This is not a big problem because I can use members of C in B.m file freely. But I always have to cast it. This feels something unclear. So I want to use better way if it is.

like image 414
eonil Avatar asked Mar 27 '11 10:03

eonil


1 Answers

There are a couple of ways of doing this, but in my opinion the best method is to use the 'PIMPL' idiom, which is fairly common in C++. Make the headers pure Objective-C and pure C++, with pointers to a forward-declared struct containing the actual implementation. This is defined in the .mm file, and can then use Objective-C++.

In your example, you would do something like this:

// B.h, pure Objective-C:
struct BImpl;
@interface B
{
    struct BImpl* impl;
}
// ...


// B.mm, mixed:
#include "C.h"
struct BImpl // since this is C++, it can actually have constructors/destructors
{
    C* my_c;
    BImpl() : my_c(new C) {}
    ~BImpl() { delete my_c; my_c = NULL; }
};
// make sure to alloc/initialise impl (using new) in B's init* methods,
// and free it (using delete) in the dealloc method.

I've actually written an article on solving exactly this problem, you might find it useful: http://philjordan.eu/article/strategies-for-using-c++-in-objective-c-projects - it also shows some other ways of doing it, including your original void* approach.

like image 51
pmdj Avatar answered Oct 18 '22 08:10

pmdj