Search code examples
c++objective-cobjective-c++mixing

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.


Solution

  • 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.