Mirror of MacCompanion

macCompanion My AppleSpace Forum Archives Products Services About Us FAQs





eCost Software Logo

Find any latest Software like Macintosh Software, Apple Mac OS X, Final Cut Studio, Final cut express, Aperture 2 & many more...

Shop at CheckCostUK.

Read reviews & compare prices on Laptop<, Apple Laptop, Apple computer, iPod, PDA, MP3 Player & many more....



Evo Networks

Latest Joy of Tech!
Latest Joy of Tech!

3-Rivers Synergy Centre

Visit StepHouse Networks. Broadband DSL for Apple Users






"Foreign" Macs



Link Lists

Mac 3D


Mac Jobs

MUG Shots




Think Different



According to Hoyle...

Objective-C for C++ Programmers,

Part II

October 2008

by Jonathan Hoyle



Last month, we began our look at the Objective-C programming language from the perspective of a C++ programmer.  In particular, we discussed class declarations and definitions as well as bracket syntax for method invocation.  This month, we continue this investigation by looking at class construction and destruction.



Class Instantiation in C++

When constructing an object in C++, two things take place: first memory allocation, then object initialization (via a call to the class constructor method).  Typically, these two things happen in the same call, so the C++ user does not have to think about it.  For example, let us suppose we have a class named Foo which has a default constructor (that is, one which takes no parameters).  We can create a new Foo object, called foo in this way:

Foo  *foo = new foo;

In this case foo is a pointer to a newly instantiated Foo object allocated from the heap.  If we don't want to deal with pointers and are willing to allocated off the stack, we can simplify this:

Foo  foo;

TIn either case, memory has been reserved and foo's constructor, and any super class constructors, have been called and completed.  foo is now ready to use.

For constructors taking parameters, the syntax is as you would expect:

Foo  *foo1 = new Foo(parm1, parm2);
    Foo  foo2(parm1, parm2);

If no constructors are declared at all, an implicit default constructor assumed.

C++ constructors will implicitly call its super class constructors in inheritance order, so that you needn't worry about it.  Whether Foo is a subclass 10 generations deep, or no subclass at all, you needn't worry.

C++'s convenience of combining allocation with initialization is often underestimated, as it is a common practice in most other modern languages.  It is not until you use a language lacking this convenience, such as Objective-C, do you come to fully appreciate it.

Note: Advanced C++ users are aware of times when you wish to decouple these steps.  For example, suppose you have previously allocated memory (stack or heap, it doesn't matter) into which you wish to instantiate your object.  Although this is relatively uncommon, C++ allows you to do this straightforwardly as well.  For example, if you wish to allocate a Foo object in an area of memory pointed at by ptr, you use the in-place new syntax:

    foo = new (ptr) Foo;




Class Instantiation in Objective-C

As suggested above, Objective-C treats memory allocation and class initialization separately.  For the former case, it is the class alloc method, and it is heap based only (no stack based objects like in C++).  The syntax is simple enough:

Foo  *foo = [Foo alloc];

An additional nicety is that the Objective-C alloc method zeroes out the memory allocation for you.  Now, since no initialization has been performed yet, the above line is analogous to the C++ lines:

    Foo  *foo = (Foo*) malloc(sizeof(Foo));
    memset(foo, 0, sizeof(Foo));

That is, you now have a pointer to an allocation of cleared memory, but you do not yet have a valid object.  You now have to perform the next step of initialization.  This is a class method that is usually (but not always) called init.  Traditionally, the name of any initialization method begins with the word "init" (but is not required to be so).  So typically the next line would look like this:

    foo = [foo init];

Now you will notice that the foo object has been reassigned after initialization.  The reason for this is that a different object may be returned after initialization, making the original pointer invalid.  So although simply calling:

    [foo init];

is syntacticly valid, the foo you are left with may be a dangling pointer, and you can quickly become hosed using it.  Objective-C users will typically chain their alloc and init calls to achieve the same effect of C++ construction.  Thus in one line, you often see:

Foo  *foo = [[foo allocinit];

Just as with C++, Objective-C initializers may take parameters, as in the following example:

     Foo  *foo = [[foo alloc] initParm1:parm1, andParm2:parm2];

Note also that Objective-C initializers must call their super class initialization methods explicitly, as there is no implicit initializer as there is in C++.




Error Handling with Object Instantiation

In C++, the philosophy is essentially this: object construction is assumed to succeed.  A failure is an exceptional situation, and therefore is typically managed by exception handling.  On modern machines, memory allocation should almost never fail, as the hard drive is used for virtual memory as need.  In the extreme situation where it does, the new operator will throw a bad_alloc exception.

Likewise, C++ constructors do not return a value, so they are always assumed to succeed.  If a C++ programmer wishes to indicate a failure to construct, he would throw an exception to this effect.

In Objective-C, both alloc and init can fail, and each one may return a NULL pointer in such an instance.  This is very similar to the no throw syntax of C++:

     foo = new (std::nothrowFoo;

For this reason, newly allocated object pointers must be checked for NULL.




Destructing Objects

Analogous to C++ construction, both object clean up and deallocation all happen together during destruction.  If the object was created on the stack, then the programmer does nothing...literally destruction takes place as the object leaves its scope.  For objects that were create on the heap with the new operator, an reciprocal call of delete is made, as such:

    delete foo;     // Cleanup and deallocate the object

And as expected, C++ inherited destructors are called in reverse order of its construction, all prior to deallocation.  Since foo is no longer a pointer to valid data, it is common to see it assigned to NULL after its destruction.  C++ destructors also quietly handle the case in which foo is already NULL, safely doing nothing.

As with C++, the Objective-C dealloc method is used for both cleanup and deallocation, as so:

   [foo dealloc];  // Cleanup and deallocate the object

That these two steps are combined for destruction, but not for construction, is just one of those Objective-C peculiarities that you will eventually grow used to.




Arrays of Objects

C++ also has the very nice feature of allocating arrays of objects, as easily as it does single objects.  Let us say for example, we wish to allocate say 10 Foo objects, not just one.  Object construction and destruction look nearly identical to their originals:

    foo = new Foo[10];  // Construct an array of 10 Foo's
    ...                 // Do stuff with these Foo's
    delete [] foo;      // Destruct these Foo's

The additional brackets (required for both construction and destruction).

Unfortunately, Objective-C has no such facility built into its allocation method.  Instead, an NSArray object must be constructed, which is a bit more complicated.  We will delve into that topic when we examine Objective-C container classes.  For now, this is where we'll stop.


Coming Up Next Month:  More Objective-C.  See you in 30!


See a list of all the According to Hoyle columns 


Mirror of: