C++ Versus Objective-C
mactech.com
mactech.com
Not once when using Obj-C have I ever said, "Wow, that was so easy thanks to Obj-C!!!" I am more likely to curse the heavens as to why the debugger can't show me the contents of any basic container type.
Going forward my work will be as heavily cross-platform C++ as I can make it. The UI may be done through platform native interface constructs, but everything I can possibly make C++ I will.
I don't disregard your perspective, mine is just exactly the opposite (I would prefer ObjC/Cocoa to C++/<Framework of your choice>, no contest).
Obj-C can absolutely accomplish most anything that C++ can, but I don't think the language makes of it easier. Once you've learned that GDB even exists and figured out many of the strange syntax nuances it's passable, but in my opinion not easier.
By comparison going from C++ to C#, Lua, or Python (my personal experiences) is astonishingly easy. Not just easy at first but continuously surprising at how many wonderful things you can do and how easy it is. As I said in my root post not once have I ever said "holy shit Obj-C sure made this task easy!"
You can mouse over an NSArray or NSDictionary and see its size and contents. You're not as familiar with the tools.
I have your same complaint, but about C++. I'm frustrated that I can't easily see the contents of a std:set or std:map in xcode. I'd be thrilled to find out if it's just a gap in my knowledge, though.
:(
I find Objective-C refreshing when compared to C++ ( take inheritance for example...in C++ I need to redeclare functions I'm overriding from my base class. Every change needs this. What a pain! Not so in Objective-C).
Having said that, I can't say how it compares to C#.
NSArray* x = ...
NSLog(@"x is %@", x);
That shows you the entire array. And there are other ways.What do you find atrocious about it? Perhaps it's something I'm missing as I haven't used Visual Studio's debugger in forever (or Eclipse, or Qt Creator)..
In C++, you have std::shared_ptr (or boost::shared_ptr and many others) which do automatic reference counting (although you specify it explicitly that these pointers have automatic reference counting; there is no way to simply enable it for all raw pointer types).
Technically, C++ is not a superset of C. And each new release of either language has them get more incompatible with one another.
I don't really know when exactly was this added to NeXT/Cocoa API, but I think it's important to note.
C++ is a standards based language available across multiple platforms and the other one isn't.
https://developers.google.com/native-client/faq#ProgrammingL...
Obj-C is an open standard language. Foundation is a proprietary library with some key stuff even PATENTED by Apple (for example, the AutoRelease Pool falls into some of the Apple patents).
[1] http://webstore.ansi.org/RecordDetail.aspx?sku=INCITS%2fISO%...
Technically untrue, C++ is a standardized language, the standard was created after the language. Ada is a standards-based language. So's haskell. The first C++ implementation (as well as "The C++ Programming Language") were released in 1985, while the first C++ "standard" was released in 1998 (ISO/IEC 14882:1998).
> available across multiple platforms and the other one isn't.
Objective-C is available on pretty much any platform on which GCC or Clang runs, actually.
#include <cstdio>
#include <functional>
using std::printf;
using std::function;
function<int ()> f(int x)
{
function<int ()> g = [x]()
{
return 2 * x;
};
return g;
}
int main()
{
auto f1 = f(5);
auto f2 = f(6);
printf("f1() = %d, f2() = %d\n", f1(), f2());
return 0;
}
(Which prints `f1() = 10, f2() = 12`)Or did you mean nested functions in the sense of being able to form named closures so that they can call themselves with a headache? It is admittedly more or a pain to do that (if you want to return a closure), but it is still doable, using new and delete:
#include <cstdio>
#include <functional>
using std::printf;
using std::function;
function<int (int)>* f(int x)
{
function<int (int)>* g = new function<int (int)>();
*g = [g, x](int n)
{
if(n <= 0)
return 1;
else
return x + n * (*g)(n-1);
};
return g;
}
int main()
{
auto f1 = f(0);
auto f2 = f(1);
printf("f1() = %d, f2() = %d\n", (*f1)(5), (*f2)(5));
delete f1;
delete f2;
return 0;
}
Or did you mean something else?Edit: Or, you could do something Y-combinator-ish like this: http://rosettacode.org/wiki/Y_combinator#C.2B.2B but yeah, it is a bit of a hassle compared to named nested functions.
Firstly, destruction upon leaving scope in Objective-C would add some magic unexpected behavior that doesn't conform to what we expect from standard C stack-based functions.
In C++, when an object is normally declared, it exists on the stack, therefore it will disappear when the scope ends. The fact that the destructor is called is nice.
In Objective-C, all objects exist solely on the heap. All object-orientation is done at runtime, not at compile time, which leaves it open to be a lot more dynamic and open to fiddling at run time than C++ is. This of course loses a lot of the speed that C++ has, but it's not a big deal in most standard applications.
Since creating an object requires specifically allocating it on the heap, having it destruct when the pointer leaves scope is no good. That kind of magic behavior is exactly what would lead to awful bugs in Obj-C. If you want short-lived objects, you call their autoreleased constructors, which means they will self-destruct next time the thread's event loop ticks. It's an extremely common pattern, and happens so often in code that you don't, as you claim, 'have to understand the details of the implementation'.
And there's absolutely no need for the derision in your post. Please make your points and defend them like a civilized person.
It is actually possible for compilers to help out with this in many cases: http://en.wikipedia.org/wiki/Escape_analysis
You don't know what `unwind-protect` is now do you?
The key thing is that it acts like a wrapper around a try/catch/finally-like block (including other forms of flow control), while allowing you to put arbitrary code in the execute and cleanup portions. You would get the same effect with RAII, most of it would be taken care of for you with the right RAII classes, and if you needed custom code then just write a custom RAII like class or be smart about handling it.
Although the C++ version wouldn't handle C's longjmp and also goto's. But if you use them you're not exactly coding in C++ then.
As much as I'm a fan of RAII in C++, it really is a "pure C++" idiom. If a C++ class is needed in Objective-C code that can @throw an NSException, then the C++ cleanup code really has to be invocable explicitly (because the destructor might not be called). For example:
MyCPlusPlusObject object;
@try
{
...
}
@finally
{
object.cleanup();
}I don't agree with this statement, at least for finally v RAII: RAII is far superior a tool to deal with scope and resource management, as it requires less work on the part of the resource user and is as a consequence far more secure. It also ties in with C++'s memory semantics and therefore exists "for free", which is nice. Even more so in as messy a language as C++.
RAII has issues, one being composition (a subject on which `finally` is worse, not better) and the second one being "in-place" operations, which `finally` can handle but — at the end of the day — should probably be implemented separately.
`unwind-protect` handles both case very nicely and is therefore — as far as I'm concerned — superior. Although it has an (easily dismissed) "inconvenient" over RAII of adding a special form to the language.
Smalltalk's `BlockClosure#ensure` is also quite nice in that department, though I'd say slightly inferior to `unwind-protect` as building on it is more expensive.