[英]C++ classes as instance variables of an Objective-C class
我需要混合使用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
扩展,所以它被编译为Objective-C与C ++混合, #ifdef
解锁了C ++的东西,我们去了。 当其他一些纯粹的Objective-C类导入头时,C ++的东西被隐藏起来,而且类没有看到任何特殊的东西。 这看起来像一个黑客,有更好的解决方案吗?
这听起来像是接口/ @协议的经典用法。 为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
的实例传递给这些客户端。
我最近也遇到过这个问题。 在我的情况下,协议是矫枉过正的。 我只需要保持一个指向恰好是C ++对象的数据访问对象的指针。
我所做的是使用void *
实例变量声明该类,并在实例方法中使用它时将其强制转换。
这有点像hack-y,但从概念上讲,它与Objective-C id
类型非常相似。
有什么特别的原因你不能只使用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代码时偶尔会出现问题。
您可能会发现在执行此操作时遇到问题 - 从我记得的ObjectiveC ++中您可能会发现,无法调用所包含的C ++对象的构造函数和析构函数。
不要这样做
如果你定义了一个实例变量,那么将为这个类提供两个独立的实例变量布局。 你将获得随机内存粉碎机,因为在一半的情况下为对象分配的内存将太短。 而不是ifdefing出实例变量,而是向前声明它的类型
struct CPPClass;
并在ivar中有一个指向它的指针,然后在你的init
/ dealloc
方法中调用new / delete来创建对象。 如果您有多个对象,则可以创建一个结构来直接保存所有C ++ ivars,然后只创建/删除该结构。
请参阅此主题以获取更多详细信息以及更多信息链接,包括详细讨论ObjC ++的播客: 我可以在编译和链接中将C ++主函数和类与Objective-C和/或C例程分开吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.