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++.
我混合了Objective-C和c++。但是我想最小化使用objective - c++。因为它在Objective-C和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.
我想包括C。在B h。h,但是如果我这么做了,B。h不能导入到A.h中,所以我必须保留变量c为void*类型。这不是一个大问题,因为我可以在B中使用C的元素。*m文件。但我总是要投。这个感觉不清楚的东西。我想用更好的方法。
2 个解决方案
#1
15
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++.
有几种方法可以做到这一点,但在我看来,最好的方法是使用“PIMPL”习语,这在c++中相当常见。使header纯Objective-C和纯c++,具有指向包含实际实现的前声明结构的指针。这是在.mm文件中定义的,然后可以使用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.
我确实写过一篇关于解决这个问题的文章,你可能会发现它很有用:http://philjordan。eu/article/ strategy -for use -c+ in-objective-c-projects -它还展示了一些其他的方法,包括您最初的void*方法。
#2
4
As pmjordan wrote in his blog article, BImpl within @interface declaration needs 'struct' keyword as follows.
正如pmjordan在他的博客文章中所写,@interface declaration中的BImpl需要“struct”关键字,如下所示。
struct BImpl;
@interface B
{
struct BImpl* impl;
}
I think he inadvertently left this out. In case you need to include this header when you have a lot of *.m files, this makes a huge difference. The added 'struct' keyword causes Objective-C compiler to understand this header as pure C for other .m files which import this header. Otherwise other *.m files which import this header won't be compiled. This small solution saves you from changing the *.m files to .mm files. Sometimes, changing original .m files to .mm causes a lot of compile errors.
我认为他无意中漏掉了这个。如果你需要包含这个标题,当你有很多*。m文件,这有很大的不同。添加的“struct”关键字会导致Objective-C编译器将这个头文件理解为纯C。否则其他*。导入该头的m文件不会被编译。这个小的解决方案可以避免您更改*。m文件到.mm文件。有时,将原始的.m文件更改为.mm会导致很多编译错误。
#1
15
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++.
有几种方法可以做到这一点,但在我看来,最好的方法是使用“PIMPL”习语,这在c++中相当常见。使header纯Objective-C和纯c++,具有指向包含实际实现的前声明结构的指针。这是在.mm文件中定义的,然后可以使用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.
我确实写过一篇关于解决这个问题的文章,你可能会发现它很有用:http://philjordan。eu/article/ strategy -for use -c+ in-objective-c-projects -它还展示了一些其他的方法,包括您最初的void*方法。
#2
4
As pmjordan wrote in his blog article, BImpl within @interface declaration needs 'struct' keyword as follows.
正如pmjordan在他的博客文章中所写,@interface declaration中的BImpl需要“struct”关键字,如下所示。
struct BImpl;
@interface B
{
struct BImpl* impl;
}
I think he inadvertently left this out. In case you need to include this header when you have a lot of *.m files, this makes a huge difference. The added 'struct' keyword causes Objective-C compiler to understand this header as pure C for other .m files which import this header. Otherwise other *.m files which import this header won't be compiled. This small solution saves you from changing the *.m files to .mm files. Sometimes, changing original .m files to .mm causes a lot of compile errors.
我认为他无意中漏掉了这个。如果你需要包含这个标题,当你有很多*。m文件,这有很大的不同。添加的“struct”关键字会导致Objective-C编译器将这个头文件理解为纯C。否则其他*。导入该头的m文件不会被编译。这个小的解决方案可以避免您更改*。m文件到.mm文件。有时,将原始的.m文件更改为.mm会导致很多编译错误。