2011-03-27 11 views
7

Estoy mezclando Objective-C y C++. Sin embargo, quiero minimizar el uso de Objective-C++. Porque tiene algún tipo de límites tanto en Objective-C como en C++.¿Forma recomendada de usar la clase C++ en la clase Objective-C minimizando el uso de Objective-C++?

Actualmente, lo estoy usando así.

// 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 
{ 
}; 

quiero incluir en C.hB.h, pero si lo hice, B.h no se pueden importar en A.h. Así que tengo que dejar la variable c como void* tipo. Esto no es un gran problema porque puedo usar los miembros de C en el archivo B.m libremente. Pero siempre tengo que lanzarlo. Esto se siente algo confuso. Así que quiero usar una mejor manera si es así.

Respuesta

15

Hay un par de formas de hacerlo, pero en mi opinión, el mejor método es utilizar el 'PIMPL' idiom, que es bastante común en C++. Haga que los encabezados sean puros Objective-C y C++ puro, con punteros a una estructura forward-declarated que contenga la implementación real. Esto se define en el archivo .mm y puede usar Objective-C++.

En el ejemplo, tendría que hacer algo como esto:

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

De hecho, he escrito un artículo en la solución de este problema exactamente, puede que le resulte útil: http://philjordan.eu/article/strategies-for-using-c++-in-objective-c-projects - sino que también muestra algunas otras formas de hacerlo, incluido el enfoque original void*.

+4

¡No puedo esperar los 4 minutos restantes para elegir esto como respuesta! – Eonil

4

Como pmjordan escribió en his blog article, BImpl dentro de @interface declaration necesita la palabra clave 'struct' de la siguiente manera.

struct BImpl; 
@interface B 
{ 
    struct BImpl* impl; 
} 

Creo que lo omitió inadvertidamente. En caso de que necesite incluir este encabezado cuando tenga muchos archivos * .m, esto hace una gran diferencia. La palabra clave 'struct' añadida hace que el compilador Objective-C entienda este encabezado como C puro para otros archivos .m que importan este encabezado. De lo contrario, no se compilarán otros archivos * .m que importen este encabezado. Esta pequeña solución le evita cambiar los archivos * .m a archivos .mm. A veces, el cambio de archivos .m originales a .mm causa una gran cantidad de errores de compilación.

+0

¿Puedes agregar un enlace al artículo del blog de pmjordan? – Stephan

+0

Sí, lo hice. De hecho, pmjordan es el autor de la primera respuesta a esta pregunta. Obtuve el enlace de la respuesta original. También puedes usar el enlace original en su respuesta. – DuncanSungWKim

+1

Esta respuesta está incorporada en la primera respuesta. Realmente agradezco a @pmjordan por adoptar mi sugerencia después de publicar esta respuesta. – DuncanSungWKim

Cuestiones relacionadas