Category Archives: C++vsObjC

“Must read” article for C++ programmers looking at ObjC

See the article(and get the link here): http://theocacao.com/document.page/473

Advertisements

Boost Smart Pointers or: How I learned to Stop Worrying and Love C++

Boost smart pointers fix many of the things wrong with auto_ptr. The smart pointer library consists of

scoped_ptr <boost/scoped_ptr.hpp> Simple sole ownership of single objects. Noncopyable.
scoped_array <boost/scoped_array.hpp> Simple sole ownership of arrays. Noncopyable.
shared_ptr <boost/shared_ptr.hpp> Object ownership shared among multiple pointers
shared_array <boost/shared_array.hpp> Array ownership shared among multiple pointers.
weak_ptr <boost/weak_ptr.hpp> Non-owning observers of an object owned by shared_ptr.
intrusive_ptr <boost/intrusive_ptr.hpp> Shared ownership of objects with an embedded reference count.

The table is courtesy of the link here.

I will just go through a simple example here. For a slightly more detailed look, you can take a look at this article.

Installing Boost on Mac OS X

Compiling and installing Boost is straightforward even if it takes some time and is processor intensive–it kept both cores of my Intel Core Duo pretty busy. What you really should do is follow the more authoritative guide from the Boost folks here. Here is my summary. Disclaimer: This is not a comprehensive guide. I am not liable for any failures you might have. See the link above for a more detailed guide.

  1. Install bjam (it is a tool like make, but supposedly better). Put bjam in your PATH
  2. Invoke bjam. Step 3 shows what an invocation might look like(you can customize this to your preferences): The following command works if you have the boost_1_34_0 directory in ~/ and bjam built and set up correctly.
  3. $ cd ~/boost_1_34_0
  4. $ bjam --build-dir=/tmp/build-boost --toolset=darwin stage
  5. After a while, type in
    echo $?

    to make sure everything proceeded correctly.

  6. Try the example given on the Boost page(see here).

A smart pointer example.

I’ll be using the IT++ library for this example. Of course, you can make your own examples without the library. The concepts are what matter.

typedef boost::scoped_ptr<PAM> pam;

int main()
{
pam p(new PAM(2));

vec output;

bvec demodded_out;

bvec input = “0100100001100101011011000110110001101111001000000101011101101111011

10010011011000110010000100001″;

//The following line of code simulates the transmitter end.
p->modulate_bits(input,output);

//The following simulates the receiver end.
p->demodulate_bits(output,demodded_out);
if(demodded_out == input)
{
cout<<“Success”;
}
else {
cout<<“Failure”<<endl;
}
return 0;
}

This is basically my previous code, with some smart pointer stuff added in. Notice that I didn’t deallocate any memory(I didn’t have to).

C++ for ObjC programmers Part IV: Classes

Instead of providing a toy example, I figured I will just annotate an existing open-source C++ class. I will talk about a class in the Synthesis Toolkit(STK). I don’t talk about actually implementing classes much, so that’s for next time. Also, I haven’t compared ObjC code to C++ code since the Part I, so I will probably do that next time.

I. Basics

Let us take a look at the existing Instrument class in the Synthesis Toolkit, which is a set of libraries written in C++ for audio signal processing and computer music. Here’s the link to the file I will be talking about –> source file link.

Taking it from the top. Remember that Flute.h is analogous to the @interface file in ObjC.

00025 #ifndef STK_FLUTE_H
00026 #define STK_FLUTE_H
00027
00028 #include "Instrmnt.h"
00029 #include "JetTable.h"
00030 #include "DelayL.h"
00031 #include "OnePole.h"
00032 #include "PoleZero.h"
00033 #include "Noise.h"
00034 #include "ADSR.h"
00035 #include "SineWave.h"

This illustrates a classic C++ idiom. One of the few places that preprocessor directives are essential is to avoid multiple header file inclusion. The directives above say that if the symbol STK_FLUTE_H is not defined , define it and include all those header files only if STK_FLUTE_H is not defined. #endif closes the #ifndef STK_FLUTE_H block. In Objective-C(with Apple’s developer tools), one always uses #import “headerfile.h” which automatically safeguards against multiple inclusion of header files.

00037 class Flute : public Instrmnt
00038 {
00039 public:


00079 protected:
00080
00081 StkFloat computeSample( void );
00082
00083 DelayL jetDelay_;
00084 DelayL boreDelay_;
00085 JetTable jetTable_;
00086 OnePole filter_;
00087 PoleZero dcBlock_;

The protected keyword indicates that the following functions and variables will only be public to this class and the classes that inherit from this class.

00047 ~Flute();

This is a destructor: You put all your dynamic memory deallocation here, but never call this function from your own code as it gets called automatically. Remember auto_ptr<T>? I wouldn’t be surprised if the way it worked is: The memory to which the raw pointer points to is deallocated when the smart pointer’s destructor is called automatically—remember the raw pointer is “wrapped” by the smart pointer.

It turns out for the particular Flute class there is no dynamic memory allocation, so the destructor is empty(I looked at the implementation file).

In case the StkFloat and DelayL above were confusing you, they are nothing but user-defined types(either user-defined classes or typedef aliases–more on typedef later).

II. Inheritance

There is more to know about classes, but let us discuss the important topic of inheritance. Remember the “IS-A” relationship. So, a flute “is-a”(n) instrument. This might seem obvious and unnecessary, but here we are looking at models of physical instruments. Thinking a little about “IS-A” and “HAS-A”(“HAS-A” is used for composition, which is essential in the ObjC-based Cocoa framework, possibly more on this later) will go a long way in helping us design classes when we are modeling more abstract entities.

Let us briefly take a look at the “parent” class of Flute, Instrument(if you download the source code for the STK framework, you can find Instrument.h and Instrument.cpp(Instrument.cpp is analogous to @implementation). I will talk about Instrument.h available here.

class Instrmnt : public Stk
00018 {
00019 public:
00021 Instrmnt();
00022
00024 virtual ~Instrmnt();
00025
00027 virtual void noteOn(StkFloat frequency, StkFloat amplitude) = 0;

What is this virtual business? Here’s a concise description:

Within the C++ the virtual keyword identifies to the compiler that a class function may be overridden in a derived class. That is, the derived class may supply a function of the same name and argument list, but with different functionality defined in the function body.

from this link. Now, note that virtual void setFrequency(StkFloat frequency);
has a function body in Instrmnt.cpp while virtual void noteOn(StkFloat frequency,...) doesn’t. If a function body existed, it would have been found in Instrmnt.cpp. This lack of a function body is indicated by the = 0 at the end in Instrmnt.h . Why would someone not have a function body and actually declare the function? Answer: To capture the commonality of all the classes that will be derived later from the base class, so that the user might do something like this:

//Warning: untested code just used for illustration purposes
Flute flute(440.0); //some made up lowest frequency 440.0
Clarinet clarinet(450.0);
vector < Instrmnt > instrumentlist;
instrumentlist.pushback(flute);
instrumentlist.pushback(clarinet);
vector< Instrmnt > instrumentlist::iterator pos;


for(pos = instrumentlist.begin(); pos != instrumentlist.end; ++pos)
{
pos->noteOn(440.0,200.0); //contrived values

post->noteOff(50.0); //contrived value 50.0

}
Also observe that it doesn’t make sense for a generic instrument to have a noteOn function, but it does make sense for the derived classes like Flute. Note that I’m treating both flute and clarinet as instruments in the above code, which enables me to write better code, instead of handling each type of instrument in a switch statement of if-else if-else construct.

III. Virtual Destructors:

Finally, let us talk about virtual destructors. Here’s a rule of thumb from Scott Kleper and Nicholas Solter(authors of Professional C++):

Always make your destructors virtual

I would qualify that with make your destructors virtual when necessary(obviously the STK authors don’t make destructors virtual when not necessary). Suppose for a moment that Flute and Instrmnt had dynamically allocated memory, so that both the Instrmnt and Flute destructors had important deallocation code, and I had the following situation:

int main()
{
Instrmnt* instr = new Flute(440.0);
delete instr;

return 0;
}

This would call Instrmnt’s destructor and not Flute’s destructor(since I didn’t make Flute’s destructor virtual). If I had, I wouldn’t have the problem.

IV. Postscript
This is just the tip of the iceberg when it comes to talking about C++ classes. You will find more information in Bruce Eckel’s Thinking in C++ Volume I, or Professional C++ by Nick Solter and Scott Kleper

C++ for ObjC Programmers Part III: Smart Pointers

Update(May 20, 2007) — I have posted a short introduction to Boost smart pointers here.

Please Note: Smart pointer implementations other than auto_ptr<T> often use reference counting mechanisms(yes the reference counting mechanism is analogous to what you see in ObjC). I don’t talk about reference counting in C++ in this article, but I will probably talk about it in the future. I can point you to the freely available source code from the book Professional C++ here. This code demonstrates a reference-counting smart pointer implementation. I might make a few comments on the code later.

In Part II, I talked about some of the ways in which C++ differs from C. One of the complaints against C++(and C) is its manual memory management. The problems with manual memory management can be mitigated with the use of smart pointers and eliminated with a third-party garbage collector. However, garbage collectors introduce some overhead, and one has to download and ‘install’ the library. The built-in smart pointer class, auto_ptr<T> is not the fastest or best implementation of smart pointers, but it is “close enough for government work”. I probably said that I will go through the creation of classes in this iteration, but there are few C++ resources which talk about smart pointers and many that talk about class construction, so I will go through smart pointers first

There is nothing magical about smart pointers. If one understands how the stack and the heap work, then the basic premise behind smart pointers is easily understood. Here is my quick overview of the stack(Try Wikipedia for an overview of the heap for now)

(Warning: conceptual material ahead 🙂 Skip to the code if bored/confused.

The stack and the heap are two different buffers(set of memory locations in RAM). Programmers specify what will go on the stack when they actually write the program. For example , when you say int x = 0; you are adding the variable x to the stack(actually to the function’s activation record(aka stack frame), which is on the stack). What is an activation record? When I call a function say, for example z = sum(x,y), an array of information is pushed onto the stack, including, (but probably not limited to) the function parameters, local variables, and return address. Here’s a nice picture(note that the stack “grows” to the bottom). The “ESP” denotes the stack pointer, which points to the “top” of the stack. i, j, and k are the parameters to the function. This picture shows how the stack looks like immediately after the function is called.

activation record example

After the function starts executing , there has to be space for local variables:

Second Picture

Pictures courtesy of this link

So, the local variables are a, r, c, b, and w. After the function does its work, the activation record is “popped”. Okay, the old locations of a, r, c, etc. might still be the same for a short while after the activation record is popped, but the programmer is not supposed to try and use those memory locations after a function returns–because there might be another function’s local variables using the same memory locations. “Popping the activation record” is done by moving the Stack Pointer, ESP back to the top of the grey box(Previous Stack Contents).

Okay, how is this related to smart pointers. The scope of a local variable is the function in which it is defined. So an easy way to think about this is if you have a function foo:

int foo(int x, int y)

{

int one;

/* calculations here */

return one;
}

Then once the statement return one; is executed, and the } is reached, the activation record for foo(..) is popped. So a smart pointer works by “wrapping” a regular pointer inside a stack based object(the auto_ptr). Then when an auto_ptr smart pointer object is “popped”, the dynamically allocated memory which the “dumb pointer” points to is automatically deallocated , ostensibly by automatically calling delete on the dynamically allocated memory pointed to by the “dumb pointer”.

—END of potentially boring conceptual/background material———-

Here’s some code that shows how to use a smart pointer.
#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main()
{
string* new_str = new string(“hello world”);

//important line
auto_ptr < string > smrtstr(new_str);

cout<<“The string length is”<<smrtstr->length()<<endl;
return 0;
//no need to call delete or anything.
}

Now, if you plan to use smart pointers for a real project, you should invest some time to install the Boost smart pointer library (the auto_ptr has some issues when dealing with Standard Template Library containers like vectors, maps, etc)

C++ for ObjC Programmers: Part II

In Part I, I talked about the differences between static typing and dynamic typing. I previously said I won’t be able to cover C++ from the very basics. However, for those who already know C, I can give a whirlwind tour of C++. This post is a shorter one,but hopefully useful.

1 Highlights

1.1 Some differences from C
  1. Including headers: #include<iostream> as opposed to #include <iostream.h>
  2. Reference parameters instead of “Pointer parameters”: In a C swap function, you would have:void swap(int *x, int *y)
    {
    int temp = *x;
    *x = *y;
    *y = temp;
    }In C++, you would use reference parameters. You would implement swap as follows:
    void swap(int &x, int &y)
    {
    int temp = x;
    x = y;
    y = temp;
    } Here, the & symbols in front denote that the addresses, and not the value of the parameters is passed in, so the original variables(and not copies of the variables) are modified. You can also define standalone references(although this is not widely useful). You can do
    int t = 0;
    int &tref = t;
    tref++; //changes t
  3. You do not have to use preprocessor directives like #define PI 3.14159. Much better is the use of true constants like const float PI = 3.14159; You can also use enum(I have a post on enum), but usually the const float PI method is more convenient.
  4. Use inline functions instead of the dangerous macro function expansions. The compiler can choose to ignore you if it thinks the function is better left as a real function(trust the compiler if you set the optimization level high!). Example of inline function:
    inline square(double x){ return x*x;}.
    Note that this is not inline because I put it all in one line, but because the compiler “search/replaces” all function calls to square in our other code by x*x if it decides to follow our guideline. WIth inline functions, you tradeoff better performance for an increase in code size.
  5. Pointers can be used just like in C. However, when working with the STL(Standard Template Library), one often uses iterators instead of pointers.
  6. Use new and delete rather than malloc and free for dynamic memory allocation. New and delete are much easier to use, and C++ programmers can bid malloc and free a “fond farewell”–Scott Meyers. Example:int *int_ary = new int[100];
    /* more code here */
    delete[ ] int_ary; The above snippet was for dynamically allocating an array of ints(same type of syntax for array of objects). What if we just want to dynamically allocate just one object? Example:int *ptr = new int; delete ptr;

Next time: basics of C++ classes, inheritance, polymorphism, virtual functions, and smart pointers.

Meanwhile, other C++ resources: C++ Reference, Cplusplus.com (this last one is not necessary the most accurate source, but useful for a quick reference).

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