C ++类作为Objective-C类的实例变量

时间:2022-02-19 06:07:08

I need to mix Objective-C and C++. I would like to hide all the C++ stuff inside one class and keep all the others plain Objective-C. The problem is that I want to have some C++ classes as instance variables. This means they have to be mentioned in the header file, which gets included by other classes and C++ starts spreading to the whole application. The best solution I was able to come with so far looks like this:

我需要混合使用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

This works. The implementation file has an mm extension, so that it gets compiled as Objective-C mixed with C++, the #ifdef unlocks the C++ stuff and there we go. When some other, purely Objective-C class imports the header, the C++ stuff is hidden and the class does not see anything special. This looks like a hack, is there a better solution?

这有效。实现文件有一个mm扩展,所以它被编译为Objective-C与C ++混合,#ifdef解锁了C ++的东西,我们去了。当其他一些纯粹的Objective-C类导入头时,C ++的东西被隐藏起来,而且类没有看到任何特殊的东西。这看起来像一个黑客,有更好的解决方案吗?

5 个解决方案

#1


This sounds like a classic use for an interface/@protocol. Define an objective-c protocol for the API and then provide an implementation of that protocol using your Objective-C++ class. This way clients need only know about the protocol and not the header of the implementation. So given the original implementation

这听起来像是接口/ @协议的经典用法。为API定义objective-c协议,然后使用Objective-C ++类提供该协议的实现。这样客户端只需要知道协议而不是实现的头部。所以给出了最初的实现

@interface Foo : NSObject
{
    id regularObjectiveCProperty;
    CPPClass cppStuff;

}

@end

I would define a protocol

我会定义一个协议

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

and modify the original Foo declaration to

并修改原始的Foo声明

@interface Foo : NSObject <IFoo>
{
    id regularObjectiveCProperty;
    CPPClass cppStuff;
}

@end

Client code can then work with type id<IFoo> and does not need to be compiled as Objective-C++. Obviously you can pass an instance of Foo to these clients.

然后,客户端代码可以使用类型id ,而不需要编译为Objective-C ++。显然,您可以将Foo的实例传递给这些客户端。

#2


I also ran into this issue recently. In my case a protocol was overkill. I just needed to keep a pointer to a data access object that happened to be a C++ object.

我最近也遇到过这个问题。在我的情况下,协议是矫枉过正的。我只需要保持一个指向恰好是C ++对象的数据访问对象的指针。

What I did was declare the class with a void * instance variable and cast it when I use it in the instance methods.

我所做的是使用void *实例变量声明该类,并在实例方法中使用它时将其强制转换。

This is a little bit hack-y, but conceptually, it's very similar to what the Objective-C id type is.

这有点像hack-y,但从概念上讲,它与Objective-C id类型非常相似。

#3


Is there some particular reason you cannot just use Objective C++ for everything? Simply switch the compiler to Compile Sources As: Objective C++ (or rename all your source files from .cpp or .m to .mm). Then you can freely intermix your C++ and Objective C.

有什么特别的原因你不能只使用Objective C ++吗?只需将编译器切换为Compile Sources As:Objective C ++(或将所有源文件从.cpp或.m重命名为.mm)。然后你可以*地混合你的C ++和Objective C.

C++ starts spreading to the whole application

C ++开始传播到整个应用程序

What problem is there with that? If your Objective C code is doing only C/Objective C code in general, then it will almost certainly not be affected at all by being compiled as C++. There is no appreciable size or speed performance issues.

这有什么问题?如果您的Objective C代码一般只执行C / Objective C代码,那么通过编译为C ++几乎肯定不会受到影响。没有明显的大小或速度性能问题。

The only two downsides I've found are: you cannot (yet) use clang static analyser to analyseC++; some (relatively weird) C code wont work in C++, which is occasionally an issue when using third party C code.

我发现的唯一两个缺点是:你不能(还)使用clang静态分析器来分析C ++;一些(相对奇怪的)C代码在C ++中不起作用,这在使用第三方C代码时偶尔会出现问题。

#4


You might find that you have problems doing this -- from what I remember of ObjectiveC++ you may find that the constructor and the destructor for your enclosed C++ object won't get called.

您可能会发现在执行此操作时遇到问题 - 从我记得的ObjectiveC ++中您可能会发现,无法调用所包含的C ++对象的构造函数和析构函数。

#5


DO NOT DO THIS

不要这样做

If you ifdef out an instance variable, that will give two separate instance variable layouts for this class. You will get random memory smashers all over the place because memory allocated for the object in half the cases will be too short. Instead of ifdefing out the instance variable, forward-declare its type like

如果你定义了一个实例变量,那么将为这个类提供两个独立的实例变量布局。你将获得随机内存粉碎机,因为在一半的情况下为对象分配的内存将太短。而不是ifdefing出实例变量,而是向前声明它的类型

struct CPPClass;

and have a pointer to it in the ivar, then in your init/dealloc methods call new/delete to create the object. If you have several objects, you can create a struct to hold all C++ ivars directly and then just new/delete that struct.

并在ivar中有一个指向它的指针,然后在你的init / dealloc方法中调用new / delete来创建对象。如果您有多个对象,则可以创建一个结构来直接保存所有C ++ ivars,然后只创建/删除该结构。

See this thread for more detail and further links to information, including a podcast that talks at length about ObjC++: Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link?

有关更多详细信息和更多信息链接,请参阅此主题,包括详细讨论ObjC ++的播客:我可以在编译和链接中将C ++主函数和类与Objective-C和/或C例程分开吗?

#1


This sounds like a classic use for an interface/@protocol. Define an objective-c protocol for the API and then provide an implementation of that protocol using your Objective-C++ class. This way clients need only know about the protocol and not the header of the implementation. So given the original implementation

这听起来像是接口/ @协议的经典用法。为API定义objective-c协议,然后使用Objective-C ++类提供该协议的实现。这样客户端只需要知道协议而不是实现的头部。所以给出了最初的实现

@interface Foo : NSObject
{
    id regularObjectiveCProperty;
    CPPClass cppStuff;

}

@end

I would define a protocol

我会定义一个协议

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

and modify the original Foo declaration to

并修改原始的Foo声明

@interface Foo : NSObject <IFoo>
{
    id regularObjectiveCProperty;
    CPPClass cppStuff;
}

@end

Client code can then work with type id<IFoo> and does not need to be compiled as Objective-C++. Obviously you can pass an instance of Foo to these clients.

然后,客户端代码可以使用类型id ,而不需要编译为Objective-C ++。显然,您可以将Foo的实例传递给这些客户端。

#2


I also ran into this issue recently. In my case a protocol was overkill. I just needed to keep a pointer to a data access object that happened to be a C++ object.

我最近也遇到过这个问题。在我的情况下,协议是矫枉过正的。我只需要保持一个指向恰好是C ++对象的数据访问对象的指针。

What I did was declare the class with a void * instance variable and cast it when I use it in the instance methods.

我所做的是使用void *实例变量声明该类,并在实例方法中使用它时将其强制转换。

This is a little bit hack-y, but conceptually, it's very similar to what the Objective-C id type is.

这有点像hack-y,但从概念上讲,它与Objective-C id类型非常相似。

#3


Is there some particular reason you cannot just use Objective C++ for everything? Simply switch the compiler to Compile Sources As: Objective C++ (or rename all your source files from .cpp or .m to .mm). Then you can freely intermix your C++ and Objective C.

有什么特别的原因你不能只使用Objective C ++吗?只需将编译器切换为Compile Sources As:Objective C ++(或将所有源文件从.cpp或.m重命名为.mm)。然后你可以*地混合你的C ++和Objective C.

C++ starts spreading to the whole application

C ++开始传播到整个应用程序

What problem is there with that? If your Objective C code is doing only C/Objective C code in general, then it will almost certainly not be affected at all by being compiled as C++. There is no appreciable size or speed performance issues.

这有什么问题?如果您的Objective C代码一般只执行C / Objective C代码,那么通过编译为C ++几乎肯定不会受到影响。没有明显的大小或速度性能问题。

The only two downsides I've found are: you cannot (yet) use clang static analyser to analyseC++; some (relatively weird) C code wont work in C++, which is occasionally an issue when using third party C code.

我发现的唯一两个缺点是:你不能(还)使用clang静态分析器来分析C ++;一些(相对奇怪的)C代码在C ++中不起作用,这在使用第三方C代码时偶尔会出现问题。

#4


You might find that you have problems doing this -- from what I remember of ObjectiveC++ you may find that the constructor and the destructor for your enclosed C++ object won't get called.

您可能会发现在执行此操作时遇到问题 - 从我记得的ObjectiveC ++中您可能会发现,无法调用所包含的C ++对象的构造函数和析构函数。

#5


DO NOT DO THIS

不要这样做

If you ifdef out an instance variable, that will give two separate instance variable layouts for this class. You will get random memory smashers all over the place because memory allocated for the object in half the cases will be too short. Instead of ifdefing out the instance variable, forward-declare its type like

如果你定义了一个实例变量,那么将为这个类提供两个独立的实例变量布局。你将获得随机内存粉碎机,因为在一半的情况下为对象分配的内存将太短。而不是ifdefing出实例变量,而是向前声明它的类型

struct CPPClass;

and have a pointer to it in the ivar, then in your init/dealloc methods call new/delete to create the object. If you have several objects, you can create a struct to hold all C++ ivars directly and then just new/delete that struct.

并在ivar中有一个指向它的指针,然后在你的init / dealloc方法中调用new / delete来创建对象。如果您有多个对象,则可以创建一个结构来直接保存所有C ++ ivars,然后只创建/删除该结构。

See this thread for more detail and further links to information, including a podcast that talks at length about ObjC++: Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link?

有关更多详细信息和更多信息链接,请参阅此主题,包括详细讨论ObjC ++的播客:我可以在编译和链接中将C ++主函数和类与Objective-C和/或C例程分开吗?