C++ for ObjC Programmers Part I

I won’t cover C++ from the utter basics here. I will just try to impart some insight which is not readily found from the C++ resources–see the end of the post for some good ones. Use the code provided below at your own risk(some of the code below is just fragments, so it won’t compile.). I’ll mark the full listings as ”full listings”

TUTORIAL 1: TEMPLATES AND ITERATORS
I. Type Me!

The fundamental difference between C++ and ObjC is the typing involved. C++ uses static typing and ObjC uses dynamic typing. Static typing means that the types of all the variables and the return types of all functions is determined at compile-time. This way, the compiler can check to see you are not doing something stupid like appending a string to the end of an integer array. Also, with types known at compile time, the compiler is better at generating efficient machine code(with types known, the sizes in memory are known, for example). However, this is not very convenient for generic programming. What do I mean by that? Say you wanted to sort a collection of integers. Okay, you write a sort(..) function that does that. But I might want to sort a bunch of strings later. So I want a generic sort function. This can also apply to arrays. I want arrays to hold ints, strings, doubles, and whatever object I want to store 10 years from now. Well, with this static typing, I can only specify int ary[10] or string ary [10] for an array of ints and an array of strings, respectively. By the way, I might want a “higher-level” array solution, and one that’ll let me grow and shrink the size of the array without hassle. To solve this problem, Dr.Stroustrup(the creator of C++) introduced used? template-based programming. To create a generic vector(expandable/collapsible array) class, I might start with something like:

//Warning: incomplete code
template<typename T>
class Vector
{
Vector();
//etc.
}

Vector::Vector() //scope resolution operator is denoted by ::{
const int initcapacity = 100;
T* ary = new T[initcapacity];
//and so on..
}

Vector::~Vector()
{delete[] ary;}

Note that it is not advisable in most circumstances that you create your own vector, since your compiler (g++ if you are using a Mac or Linux platform) provides optimized implementations of the C++ Standard Template Library.

So using the aforementioned Standard Template Library, I can create an array of ints and an array of strings as follows:

//Full listing
#include <iostream>
#include <vector>
#include <iterator>
#include <string>
using namespace std; //so I don’t have to do std::cout, etc

int main()
{
vector<int> numbers;
vector<string> names;

numbers.push_back(5);//append
names.push_back(“hello”);
numbers.push_back(6);
names.push_back(“yellow”);

vector<int>::iterator int_pos;
vector<string>::iterator str_pos;

for(int_pos = numbers.begin(); int_pos != numbers.end(); ++int_pos)
{
cout<<“Next number: “<<*int_pos<<endl;//cout is used for output
}
for(str_pos = names.begin(); str_pos != names.end(); ++str_pos)
{
cout<<“Next name: “<<*str_pos<<endl;
return 0;
}

Note that I used iterators here.

Iterators are the analog of enumerators(NSEnumerator) in Cocoa. I could have cycled through the vectors similar to how I would have cycled through a plain C array, but the point of using iterators is that I’m abstracting away the details of how vector is implemented. That way, if the Standard Library implementor changes the implementation, my code above still works(same reason why NSEnumerators are used). Notice that when I define vector<int> numbers, etc, the compiler uses its generic vector implementation, which looks like class Vector{..} which I started above. You can think of the compiler as doing a “search and replace of T with int and T with string for vector<int> and vector<string>, respectively”.

II. Comparison with Objective-C(using Cocoa)

Note that it ObjC we do not use templates in the C++ sense because the compiler does not require that types be known at compile-time. So, instead we use the keyword “id” to mean “any type you want”. For example, you can notice id is being used in the function signature of an NSMutableArray instance method:

– (void)insertObject:(id)anObject atIndex:(unsigned)index

Whereas the C++ Standard Library implementor would have made vector(which is the analog of NSMutableArray) into a template method, the Cocoa NSMutableArray implementor just had to say “the object I want to add to the array at this index can be anything I want, like ints, NSStrings, etc”.

Here’s the above example(or something close) in Obj-C:

//Almost full listing–use the Foundation tool template in Xcode to get the rest of the scaffold like autorelease pool, etc.

//WARNING: untested code(will be tested later)
int main(int argc, const char *argv[]) {
NSMutableArray *str_ary = [[NSMutableArray alloc] init];
NSMutableArray *int_ary = [[NSMutableArray alloc] init];
NSNumber* five = [NSNumber numberWithInt:5];
NSNumber* six = [NSNumber numberWithInt:6];

[str_ary addObject: @”hello”];
[str_ary addObject: @”yellow”];
[int_ary addObject: five];
[int_ary addObject: six];

NSEnumerator *intaryenum = [int_ary objectEnumerator];
NSEnumerator *straryenum = [str_ary objectEnumerator];
NSString *thisStr;
NSNumber *thisInt;
while(thisStr = [straryenum nextObject])
{
NSLog(@”this string: %@,thisStr);
}
while(thisInt = [intaryenum nextObject])
{
NSLog(@”this int: %@,thisInt);
}
[str_ary release];
[int_ary release];

return 0;
}

Closing comments: Note that I did not have to deallocate any C++ objects(because these objects were on the stack and not the heap) As far as I know,ObjC does not allow stack-based objects. If I had instead used dynamic memory allocation for the C++ objects, I would have to deallocate the objects(not release them , like in ObjC, because C++ has no built-in reference counting mechanism).

Next time: Some differences between C and C++

After that: we’ll put some unfounded fears to rest by looking at smart pointers in C++. I’ll also talk about declaring variables vs. defining variables(Bruce Eckel talks about this too in his Thinking in C++ book). Also, classes in C++, inheritance in C++, what the keyword virtual means, when to use it, etc.

III.Non-comprehensive list of things different between C++ and ObjC

  • C++ has operator overloading and function overloading, ObjC doesn’t
  • C++ has multiple inheritance, while ObjC doesn’t(it does have protocols, though)
  • C++ does not allow you to extend existing classes, while ObjC does
  • C++ is not dynamically typed, while ObjC is
  • C++ allows template metaprogramming while ObjC doesn’t
  • C++ has namespace support while ObjC doesn’t
  • C++ allows stack-based objects while ObjC doesn’t
  • C++ doesn’t have reference counting(but has things like smart pointers), ObjC has reference counting.

There are more differences, but these are ones off the top of my head.

Let me know if you found this write-up useful(it takes a long time to write these things).

C++ references: Dr. Peter Grogono’s lecture notes, Bruce Eckel’s Thinking in C++ Volume I(just use google for this one!)

Maybe if I really feel upto it, I will talk about using C++ garbage collectors in the future.

Good reference for Standard Template Library(STL) Nicolai Josuttis’ online examples from his book here

Advertisements

One response to “C++ for ObjC Programmers Part I

  1. Pingback: C++ for ObjC Programmers: Part II « Mac OS X coding

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s