Well, there are a few fundamental differences between Objective-C and C++. In Objective-C, there is actually a "generic object" (type "id"), and you can pass objects around without worrying about classes.
One of the implementation details that makes this possible is that Objective-C doesn't have "static" objects; all objects are created through the equivalent of "new" and are accessed through a pointer (string literals might be different, but they are still of type "NSString*"). It's just the way it is in Objective-C; you simply cannot have an "NSString MyString".
Because of this, the whole "objects are just objects and the compiler doesn't actually what you're dealing with" is possible because all objects are just simple pointers -- they are all the same size. The compiler can pass them around without knowing what they are, you can store them in containers without the containers knowing what they are etc.
Objective-C and C++ may both be "object-oriented" extensions of C, but they are quite different nonetheless.
EDIT: you can write stuff like "NSString* MyString" so the compiler knows what kind of object it is dealing with, but that's just convenience: you can still put other objects into that pointer (and, in fact, since the "new" equivalent usually returns id, one of the more common mistakes that I make is to "new" a different class from what the pointer says)
On the positive side, the compiler will warn you if you assign e.g. an NSWindow* to MyString, and it will also warn you if you call "open" on MyString. However, this is just an added benefit from the compiler; you could just as well declare everything as "id", or cast away the warnings.