The syntactic additions in Objective-C were designed to highlight the various semantics of the object-oriented code. In C++, you can do this:
This can be calling a C function, calling a static C++ member function with the current object passed as a hidden parameter, or calling a virtual function, which might be implemented in a subclass, with the current object as a hidden parameter. Alternatively, you might do this:
This could be calling a C function pointer that's a field of the a structure, calling a static member function defined on the class of which you think a is an instance, or a virtual function defined on the class of which a really is an instance.
In contrast, things that look like C in Objective-C always are C. The equivalent for calling a method in Objective-C comes from the Smalltalk syntax:
The square brackets are used to wrap some Smalltalk-like message-sending syntax. I'll come back to the difference between sending messages and calling functions a bit later. When you have a method that takes some arguments, the arguments all have names in Objective-C, like this:
[aDictionary setObject:@"a string" forKey:@"a key"];
This might seem strange to someone who is more familiar with C syntax, but it means that you spend much less time thinking about the order of parameters. It also makes the code much easier to read if you haven't previously come across the class of which aDictionary is an instance—you know that this method is setting an object and a key, and you know which is which.
Under the hood, this is turned into something like the following:
SEL sel = sel_get_uid("setObject:forKey:"); IMP method = objc_msg_lookup(aDictionary->isa, sel); method(aDictionary, sel, @"a string", @"a key");
I'll come back to exactly what sel is a bit later. While this will work, it isn't quite what happens—the value of sel will be filled in by the runtime library's initialization routine when the module is loaded. The NeXT/Apple family of runtimes combine the last two steps into something like this:
objc_msgSend(aDictionary, sel, @"a string", @"a key");
This is slightly faster, but makes implementing optimizations such as speculative inlining in the future a lot harder. Because these are C functions, nothing about them is special—you can call them from your own code, if you want. One of the fun things in the LLVM C language family front end (clang) tree is a rewriter that takes an Objective-C source file and compiles it to a C source file compatible with the NeXT runtime library.