Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disadvantages of Objective-C++? [closed]

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.

like image 610
Luke Avatar asked Nov 08 '11 19:11

Luke


People also ask

Is Swift or Objective-C better?

Swift is easier to read and easier to learn than Objective-C. Objective-C is over thirty years old, and that means it has a more clunky syntax. Swift streamlines code and more closely resembles readable English, similar to languages like C#, C++, JavaScript, Java, and Python.

Is Objective-C slow?

Objective C messaging is slow relative to accessing lots of small data type elements (every pixel in a large image bitmap or every audio sample in an entire song) inside innermost loops. Objective C is really fast relative to doing anything at the rate of UI or even display refresh events.

What is the main difference between Objective-C and swift?

Swift is a general-purpose, high-level programming language which is highly concerned about safety, performance. Objective C is an general purpose language which is considered as superset of C language it was designed in an aim of providing object-oriented capabilities. 02.

Is Objective-C still supported by Apple?

Community & supportAlthough Objective-C is still supported by Apple, it has never been an open-source language.


1 Answers

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.

like image 71
justin Avatar answered Sep 22 '22 03:09

justin