Class Declaration: C++ vs. Objective-C

It is hard to show with a single example all the differences between Objective-C and C++ for class declaration and implementation. In the following, the differences are exposed sequentially and specifically.

Basic Difference

Objective-C is an object-oriented language: it manages classes and objects. Objective-C uses a strict object model, unlike C++ which has many discrepancies against the ideal object model. For instance, in Objective-C, classes are objects and can be dynamically managed: it is possible to add classes at run-time, create instances based on the name of the class, ask a class for its methods, and so on. This is much more powerful than C++ RTTI.

Root class, type id, nil and Nil values

In an object-oriented language, each program makes use of a set of classes. Unlike C++, Objective-C defines a root class. Every new class should be a descendant of the root class. In Cocoa, that class is NSObject, and it provides a huge number of facilities for the run-time system.

Strictly speaking, every object should be of type NSObject, and every pointer to an object could be declared as NSObject*. In fact, one can use the type id instead. This is a short and handy way to declare a pointer to any object, and provides dynamic type-checking instead of static type-checking. It is very useful for some weak typing on generic methods. Please note that a null pointer to an object should be set to nil, not NULL. These values are not interchangeable. A normal C pointer can be set to NULL, but nil was introduced in Objective-C for pointers to objects. In Objective-C, classes are also objects (meta-class instances), and it is possible to declare a pointer to a class. Their null value is Nil.

Attributes and methods

class Test { double x; public: int f(int x); float g(int x, int y); };  int Test::f(int x) {...} float Test::g(int x, int y) {...}
@interface Test : NSObject { double x; } -(int) f:(int)x; -(float) g:(int)x:(int)y; @end  @implementation Test -(int) f:(int)x {...} -(float) g:(int)x:(int)y {...} @end

In C++, attributes and methods are declared together inside the braces of the class. Method implementation syntax is similar to C, with the addition of the scope resolution operator (Test:: ).

In Objective-C, attributes and methods cannot be mixed. The attributes are declared in braces, the methods follow. Their implementation lies in an @implementation block. This is a major difference with C++, since some methods can be implemented without being exposed in the interface. Briefly, this is a way to clean up header files by removing unnecessary declarations

Instance methods are prefixed by the minus symbol “-”, and class methods by the plus symbol

“+”; this symbol has nothing to do with the UML notation and the meaning public or private. The type of the parameters is enclosed in parenthesis, and the parameters are separated by the symbol “:”.

In Objective-C, there is no need for a semi-colon at the end of a class declaration. Also note that the keyword to declare a class is @interface and not @class. The keyword @class is only used in forward declarations. Finally, if there is no instance data in a class, the braces, which would enclose nothing, can be omitted. Forward declarations: @class, @protocol

To avoid cyclic dependencies in header files, in C++ uses keyword class is used; in Objective-C, it is @class. The keyword @protocol can also be used to anticipate the declaration of a protocol.

//In file Test.h #ifndef __TEST_H__ #define __TEST_H__ class Bar; //forward declaration class Test { Bar* bar; public: void useBar(void); }; #endif
//In file Test.cpp #include "Test.h" #include "Bar.h" void Test::useBar(void) { ... }
//In file Test.h @class Bar; //forward declaration @interface Test : NSObject { Bar* bar; } -(void) useBar; @end
//In file Test.m #import "Test.h" #import "Bar.h" @implementation Test -(void) useBar { ... } @end

public, private, protected

One major feature of the object model is data encapsulation, which limits the visibility of data to some parts of the code, in order to ensure its integrity.

class Test { public: int x; int apple(); protected: int y; int pear(); private: int z; int banana(); };
@interface Test : NSObject { @public int x; @protected: int y; @private: int z; } -(int) apple; -(int) pear; -(int) banana; @end

In C++, attributes and methods can belong to a public, protected or private scope. The default mode is private.

In Objective-C, only the instance data can be public, protected or private, and the default visibility is protected. Methods can only be public. However, it is possible to mimic the private mode, by implementing some methods in the @implementation, without declaring them in the @interface, or using the notion of class category. It does not prevent methods from being called, but they are less exposed. Implementing a method without a previous declaration is a special property of Objective-C.

Inheritance cannot be tagged public, protected or private. The only way is public.

static attributes

It’s not possible in Objective-C to declare a class data attribute (static as in C++). However, it is possible to do the same thing in a different way: use a global variable in the implementation file (optionally with the static C keyword to limit the scope). The class can then use accessors on it (with class methods or normal methods), and its initialization can be done in the initialize method of the class.