Objective-C ++的缺点? [英] Disadvantages of Objective-C++?

查看:118
本文介绍了Objective-C ++的缺点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Objective-C ++中为iOS编写了一个大型项目。我主要使用Objective-C用于UI和其他Apple API,以及C ++用于内部音频处理和其他信息处理。我想知道自由混合Objective-C和C ++的缺点。



当然,混合两个对象模型有其固有的局限性和潜在的混乱和混乱。我更好奇的是如何使用Objective-C ++将影响编译过程,我可能遇到的句法错误,可读性的问题和我可能会避免这些等。我有兴趣听到你的经验Objective-C ++有

解决方案

ObjC ++非常强大 - 您可以选择和混合您需要的功能为您的问题和接口与C,ObjC和C + +所有在同一时间。我一直在使用它多年。当然,有一些注意事项,很高兴知道它们,以便您可以尽量减少可能遇到的问题:



编译



开始创建非平凡程序时,编译时间远远高于ObjC或C ++。



在ObjC类型中声明您的C ++类型的常见方法很少:




  • 不透明类型


  • 使用智能指针转发声明

  • 按值



我只是掩饰这一点,因为它是从OP推断,你熟悉两种语言。



给定C ++类型:

  class t_thing {public:int a; }; 

您可以通过多种方式声明您的ivar:



不透明类型:

  @interface MONClass:NSObject {void * } @end 

这应该避免。删除类型安全不好。



此变体与ObjC翻译兼容。



转发声明:

  class t_thing; 
@interface MONClass:NSObject {t_thing * thing; } @end

这比不透明类型好,但是智能指针更好 - 如果你习惯于编写现代的C ++。



这个变体与ObjC翻译兼容,只要你的C ++类型在全局命名空间。



使用智能指针转发声明:



  class t_thing; 
@interface MONClass:NSObject {t_smart_pointer< t_thing>事情; } @end

这是最好的,如果你打算设置翻译防火墙转发以减少依赖性)。同样,ObjC对象已经经历了锁定和分配,因此分配C ++类型不是一个坏点。如果您有多个声明,您可能希望为实施创建一个封装类型,以减少个别分配。



此变体不是兼容ObjC翻译。



这是一个好时机,提醒您有一个编译器选项与ObjC ++,你应该启用: GCC_OBJC_CALL_CXX_CDTORS 。当此标志设置时会发生什么?编译器生成隐藏的objc方法,它调用你的C ++ ivars的构造函数和析构函数。如果使用 GCC_OBJC_CALL_CXX_CDTORS ,您的C ++ ivars必须是默认构造的。如果不启用此标志,则必须手动构建和销毁您的ivars 完美 - 如果构建它两次或不覆盖子类的初始化器,那么您将面向UB。



按值:

  #include hpp
@interface MONClass:NSObject {t_thing thing; } @end

最高依赖项。这是(一般)我选择的路线,我有一些遗憾。我刚刚移动了一些东西,使用更多的C ++,并使用智能指针(如上所述)组合以减少依赖。



此变体不是与ObjC翻译兼容。



现代ObjC编译器的另一件事:编译器在二进制文件中展示你的C ++类型的ivars /结构。不管你信不信,这会消耗大量的二进制空间。



这里的重点是程序可以有多种形式。你可以混合这些技术来减少依赖性,这是引入依赖性防火墙的最好的地方之一,因为ObjC是非常动态的(它的方法必须在一个翻译中导出),并且对象创建需要分配,锁定,引入引用计数系统 - 单个对象的初始化时间已经相对较高,并且实施将始终被隐藏。



如果您的程序的大部分仍在ObjC中,这样,你将需要使用在全局命名空间中声明的类型的转发,或者通过对象工厂提供专门化的不透明基本类型。个人而言,我只是使用这么多的C ++,这不是一个理想的选择,并且全局类型的包装实现很快变得令人讨厌。



同时,由于编译时间很高, inverse is true:如果你可以将你的实现的重要部分保存为C ++,那么你将节省大量的编译时间。因此,和ARC(下面),你可以通过保持原始的苹果类型作为CF类型尽可能多的,所以你可以继续构建C ++程序没有ObjC扩展很多。



语法



我很少遇到问题,但我保持我的C ++类非常严格:

$
$ b

  • 我默认禁止复制和分配。

  • 我很少声明C ++类型的自定义运算符。 b $ b


如果你对C ++非常感兴趣,那么你可以避免这个问题,但我更喜欢编译器捕获我犯的错误。



一个明显的问题是在ObjC消息发送中的C ++范围解析。这需要一个空格:

  [obj setValue ::: func(a)]; //<< bad 
[obj setValue::: func(a)]; //<<好

可读性



我遇到的一个问题是我从来没有找到支持ObjC ++语法的代码格式化程序。



ObjC消息 p>


  • ObjC消息和返回值:您需要在消息之前检查 nil 当按值返回C ++类型时。如果你消息的对象是 nil ,那么结果将是现代运行时(x86_64和iOS)上的零内存。


  • ObjC消息传递并通过引用返回:您需要在消息之前检查 nil 时返回C ++类型。如果你消息的对象是 nil ,那么结果将是未定义的行为(引用 0 / NULL )。 / p>




为了克服ObjC消息传递问题,我通常使用如下形式:

   - (bool)selector:(std :: string&)outValue; 

其中返回值为false表示某些内部错误,true表示成功。



那么你可以安全地写:

  if(![obj selector:outString] {/ * bail here * /} 

Miscellanea b
$ b


  • ARC兼容性:ObjC ++不适合ARC。主要原因是ARC不遵循混合对象模型。示例:如果您尝试将ObjC成员放入C ++类型,编译器将拒绝ARC下的程序。这不是一个真正的问题,因为MRC很简单与ObjC ++(假设你也使用SBRM),但它可能是一个关注你的程序的生命周期。


  • p>合成属性:您将必须为C ++类型定义属性。


  • 外部工具:除了Xcode的工具集,有几个程序处理或识别ObjC ++好。文本编辑器,IDE,实用程序。


  • Apple的工具:在Xcode的实用程序中,Xcode对ObjC ++的支持有点低。重构(不可用),导航(改进与铛解析器),大纲(相当原始),ObjC ++可以扰乱IB的实用程序,项目升级通常不被支持。



I'm writing a large project for iOS in Objective-C++. I'm mainly using Objective-C for the UI and other Apple APIs, and C++ for internal audio processing and other information handling. I was wondering about the drawbacks of mixing Objective-C and C++ freely.

Of course, mixing two object models has its inherent limitations and potential for messiness and confusion. I'm more curious about how using Objective-C++ will affect the compilation process, syntactic pitfalls I might run into, problems with readability and how I might avoid those, etc. I'm interested to hear what your experiences with Objective-C++ have been like and tips you might have for approaching this.

解决方案

ObjC++ is extremely powerful - you can select and mix the features you need for your problems and interface with C, ObjC, and C++ all at the same time. I've been using it for many years. There are of course, a few caveats, and it's good to be aware of them so you can minimize the issues you might encounter:

Compilation

The compilation times are much higher than ObjC or C++ when you begin creating nontrivial programs.

There are a few common approaches to declaring your C++ types in ObjC types:

  • Opaque types
  • Forward Declarations
  • Forward Declarations with smart pointers
  • By value

I'll just gloss over this, as it is inferred from the OP that you are familiar with both languages. As well, this is one of the more publicly written about introductory topics on ObjC++.

Given the C++ type:

class t_thing { public: int a; };

You have a number of ways to declare your ivars:

Opaque type:

@interface MONClass : NSObject { void* thing; } @end

This should be avoided. It's not good to erase type safety. The two forward options will introduce type safety.

This variant is compatible with ObjC translations.

Forward Declaration:

class t_thing;
@interface MONClass : NSObject { t_thing* thing; } @end

This is better than an opaque type, but the smart pointer is even better - pretty obvious if you are used to writing modern C++.

This variant is compatible with ObjC translations as long as your C++ types are in the global namespace.

Forward Declaration using smart pointers:

class t_thing;
@interface MONClass : NSObject { t_smart_pointer<t_thing> thing; } @end

This one is the best if you intend to set up translation firewalls (e.g. use PIMPL and forwards to reduce dependencies). As well, the ObjC object is already going through locking and allocations, so it's not a bad point to allocate a C++ type. If you have several declarations, you may prefer to create a wrapper type for your implementation to reduce individual allocations.

This variant is not compatible with ObjC translations.

This is a good time to remind you that there is a compiler option with ObjC++ that you should enable: GCC_OBJC_CALL_CXX_CDTORS. What happens when this flag is set? The compiler produces hidden objc methods which invoke your C++ ivars' constructors and destructors. If you use GCC_OBJC_CALL_CXX_CDTORS your C++ ivars must be default constructible. If you do not enable this flag, you must manually construct and destruct your ivars perfectly - if you construct it twice or do not override an initializer of the subclass, then you are facing UB.

By value:

#include "thing.hpp"    
@interface MONClass : NSObject { t_thing thing; } @end

Highest dependency. This is (in general) the route I chose, and I have some regrets about that. I've just moved things over to use more C++ and use composition with smart pointers (outlined above) to reduce dependency.

This variant is not compatible with ObjC translations.

One other thing about the modern ObjC compilers: The compiler lays out your C++ types' ivars/structure in the binary. Believe it or not, this can consume a lot of binary space.

The point here is that there are multiple forms the program can take. You can mix these techniques to reduce dependency, and this is one of the best places to introduce dependency firewalls because ObjC is very dynamic (its methods must be exported in one translation), and object creation requires allocations, locks, introduction into the reference counting system - initialization time for a single object is already relatively high, and the implementation will always be hidden.

If much of your program is still in ObjC and you want to keep it that way, then you will need to resort to forwards of types which are declared in the global namespace or opaque base types which you vend specializations through an object factory. Personally, I just use so much C++ that this was not an ideal option, and wrapping implementations in global types quickly became tiresome.

Meanwhile, since compilation times are high, the inverse is true: If you can keep significant portions of your implementation as C++, then you will save a lot of compilation time. For this reason and ARC (below) you can gain a lot by keeping your primitive Apple types as CF types where possible, so you can continue building C++ programs without the ObjC extensions.

Syntax

I rarely have problems but I keep my C++ classes quite strict:

  • I prohibit copy and assignment by default.
  • I rarely declare customized operators for C++ types.

If you're awesome at C++, then you could avoid this problem, but I prefer the compiler to catch silly mistakes I make.

One evident problem is C++ scope resolution within an ObjC message send. This requires a space:

[obj setValue:::func(a)]; // << bad
[obj setValue: ::func(a)]; // << good

Readability

One problem I have encountered is that I have never found a code formatter that supports the ObjC++ syntax well.

ObjC Messaging

  • ObjC Messaging and return by value: You need to check before messaging nil when returning C++ types by value. If the object you message is nil, then the result will be zeroed memory on the modern runtimes (x86_64 and iOS). If you use that instance, it is undefined behaviour.

  • ObjC Messaging and return by reference: You need to check before messaging nil when returning C++ types by reference. If the object you message is nil, then the result will be undefined behaviour (reference to 0/NULL).

To overcome the ObjC Messaging issues, I typically use a form like this:

- (bool)selector:(std::string&)outValue;

where the return value is false for some internal error, and true for success.

then you can safely write:

if (![obj selector:outString]) { /* bail here */ }

Miscellanea

  • ARC Compatibility: ObjC++ is not good for ARC. The primary reason is that ARC does not follow through mixed object models. Example: If you try to put a ObjC member into a C++ type, the compiler will reject the program under ARC. This is not really an issue because MRC is dead simple with ObjC++ (assuming you also use SBRM), but it may be a concern for the lifetime of your program.

  • Synthesized Properties: You will have to define your properties for C++ types.

  • External Tools: Beyond Xcode's toolset, there are few programs that handle or recognize ObjC++ well. Text editors, IDEs, utilities.

  • Apple's Tools: Within Xcode's utilities, Xcode's support for ObjC++ is a bit low. Refactoring (unavailable), navigation (improved with clang parser), outlining (is rather primitive), ObjC++ can disrupt IB's utilities, project upgrading is often not supported.

这篇关于Objective-C ++的缺点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆