我需要混合使用Objective-C和C ++。我想隐藏一个类中的所有C ++内容,并保持其他所有内容的Objective-C。问题是我想要一些C ++类作为实例变量。这意味着它们必须在头文件中被提及,其被其他类包含并且C ++开始传播到整个应用程序。到目前为止,我能够提供的最佳解决方案如下:
#ifdef __cplusplus
#import "cppheader.h"
#endif
@interface Foo : NSObject
{
id regularObjectiveCProperty;
#ifdef __cplusplus
CPPClass cppStuff;
#endif
}
@end
这很有效。实现文件具有mm
扩展名,因此它被编译为与C ++混合的Objective-C,#ifdef
解锁了C ++的东西,我们就去了。当其他一些纯粹的Objective-C类导入头时,C ++的东西被隐藏起来,而且类没有看到任何特殊的东西。这看起来像黑客,有更好的解决方案吗?
答案 0 :(得分:8)
这听起来像是接口/ @协议的经典用法。为API定义objective-c协议,然后使用Objective-C ++类提供该协议的实现。这样客户端只需要知道协议而不是实现的头部。所以给出了最初的实现
@interface Foo : NSObject
{
id regularObjectiveCProperty;
CPPClass cppStuff;
}
@end
我会定义一个协议
//Extending the NSObject protocol gives the NSObject
// protocol methods. If not all implementations are
// descended from NSObject, skip this.
@protocol IFoo <NSObject>
// Foo methods here
@end
并将原始Foo
声明修改为
@interface Foo : NSObject <IFoo>
{
id regularObjectiveCProperty;
CPPClass cppStuff;
}
@end
客户端代码可以使用类型id<IFoo>
,而不需要编译为Objective-C ++。显然,您可以将Foo
的实例传递给这些客户端。
答案 1 :(得分:3)
我最近也遇到过这个问题。在我的情况下,协议是矫枉过正的。我只需要保留一个指向恰好是C ++对象的数据访问对象的指针。
我所做的是使用void *
实例变量声明该类,并在实例方法中使用它时将其强制转换。
这有点像hack-y,但从概念上讲,它与Objective-C id
类型非常相似。
答案 2 :(得分:1)
是否有一些特殊原因你不能只使用Objective C ++?只需将编译器切换为Compile Sources As:Objective C ++(或将所有源文件从.cpp或.m重命名为.mm)。然后你可以自由地混合你的C ++和Objective C。
C ++开始传播到整体 应用
那有什么问题?如果您的Objective C代码一般只执行C / Objective C代码,那么通过编译为C ++几乎肯定不会受到影响。没有明显的大小或速度性能问题。
我发现的唯一两个缺点是:你不能(还)使用clang静态分析器来分析C ++;一些(相对奇怪的)C代码在C ++中不起作用,这在使用第三方C代码时偶尔会出现问题。
答案 3 :(得分:0)
您可能会发现在执行此操作时遇到问题 - 从我记得的ObjectiveC ++中您可能会发现,无法调用随附的C ++对象的构造函数和析构函数。
答案 4 :(得分:0)
不要这样做
如果您确定了一个实例变量,那么将为该类提供两个单独的实例变量布局。你将获得随机内存粉碎机,因为在一半的情况下为对象分配的内存将太短。而不是ifdefing出实例变量,而是向前声明它的类型,如
struct CPPClass;
并在ivar中指向它,然后在init
/ dealloc
方法中调用new / delete来创建对象。如果您有多个对象,则可以创建一个结构来直接保存所有C ++ ivars,然后只创建/删除该结构。
请参阅此主题以获取更多详细信息以及更多信息链接,包括详细讨论ObjC ++的播客:Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link?