To start off with, we have to remember that Objective-C is a language and Cocoa is a framework -- i. e., a collection of objects and functions that provide all the basic building blocks necessary to create a fully-featured GUI-based (or command line based) application. While Cocoa is built using Objective-C, other languages such as Java (or even Perl or Python) can be used to build Cocoa apps. But Objective-C is the default, and in many ways, the preferred language to use.
Objective-C is a beautiful language. While it is a superset of C, which means anything you can do in C you can do in Objective-C, the reality is that the Cocoa frameworks eliminate the need to use many of the standard C data types and library functions. Cocoa provides powerful objects for storing and manipulating strings, arrays, hashes, and many other common data types, and also includes a number of useful structures such as points and rectangles for use in coding graphics routines. Cocoa objects take care of most of the hassles of memory management, leaving you to focus on the real task at hand: coding features. While you're free to intermingle regular C code using standard data types and Objective-C code using Cocoa objects all you want, the preferred way to send and receive data from the GUI side of your application is through Cocoa data objects. The major exception to this is numbers: most Cocoa objects use standard C number types like
double, because they're so simple and easy to work with.
There are a number of features to be found in Objective-C that can't be found in C++. In fact, Cocoa couldn't have been designed the way it was if NeXT had chosen C++ for its foundation. Objective-C is built around two core concepts: dynamic typing and run-time messaging (which embodies the secondary concept of dynamic binding). These concepts are mainly what sets Objective-C apart from its competitors.
Dynamic typing works like this: in Objective-C, an object identifier is a variable of type
id is defined as a C pointer to an object stored in memory. This object can be of any type, or as the proper term is, it can belong to any class. It could be a Cocoa string object, or it could be a MyBigHouse object that you've created yourself. (If you don't know what an object or a class is, don't worry, it will all be explained shortly.) Since it isn't determined until run-time, you have the ability to inspect the object and ask the object what class it belongs to before doing something with it. In a statically-typed language such as C++, you don't have this kind of flexibility, since a variable always has to be of a certain type, even if limited "late-binding" functionality is available (a C++ thing).
Now in languages such as Perl or PHP, you simply call an object method much as you would a regular function. Not so in Objective-C. In Objective-C, you use messages. Basically, you send a message to Object A saying "do this", and it does it. Methods are declared in a somewhat similar fashion to C functions, they can use multiple arguments, and they can return a value just like functions. In that case, the message is "Object A: do this and that and this and that and then give me back a response". The distinction between calling an object method directly and sending the object a message instead is subtle but important. For instance, you may not know what kind of object you're working with until run-time (because of dynamic typing), so how could the compiler know what method should be called ahead of time? Rather, because you're sending a message, the Objective-C run-time engine looks up the appropriate method of the object and calls it on behalf of your code, and then passes the return value back to you.
The really neat thing about this is that you can ask an object if it responds to a "selector" (which is a special kind of variable containing an identifier that is linked with a method name), and then "perform" the selector on the object if that method is supported. So you don't even need to know what kind of object you're working with, just as long you can send it the right kind of message. You can even "save" a message and then use it later on, which is extremely important for Cocoa's implementation of cross-application/cross-computer data communication, called "distributed objects".