Saturday, August 11, 2007

C++ for Java Programmers

I just wrote this in half an hour, but it's been on my mind since a week ago or so! This is subject to corrections as I experiment around, get feed back, etc. Revision 0: Published. Revision 1: Modified the headers to be presented correctly. Added tags. Revision 2: (16 August 2007) Added information about polymorphism. Revision 3: (19 August 2007) Added a link for systems programming in C++. Revision 4: (19 September 2007) Added information about the virtual qualifier's use in Java.

Introduction

Back when I took computer programming in High School (way way back when :P), I learned C++ but only the basics (e.g. cout, cin, endl, etc.). I only learned about object oriented programming in "AP" (the so-called "advanced placement") programming course. As one may expect, object oriented C++ was something I had learned independent of the course work (although with the help of the teacher, Dr. Neat). Well, I learned Object Oriented programming through Java...so I expect that object orientedness should be reasonably similar to Java programming. Through some experimenting and fiddling around with C++, I managed to make C++ a wee bit more java-like.

"Classes in their own files"

In java, if one were to program a new class it is typically its own file. Consider the Bicycle class from the Java tutorial reproduced below:
class Bicycle {     int cadence = 0;     int speed = 0;     int gear = 1;     void changeCadence(int newValue) {         cadence = newValue;     }     void changeGear(int newValue) {         gear = newValue;     }     void speedUp(int increment) {         speed = speed + increment;     }     void applyBrakes(int decrement) {         speed = speed - decrement;     }     void printStates() {         System.out.println("cadence:"+cadence+" speed:"+speed+" gear:"+gear);     } }
This is in Bicycle.java. Consider this code in C++ which we put in Bicycle.h:
#include < iostream > #ifndef BICYCLE_H #define BICYCLE_H class Bicycle { private:     int cadence;     int speed;     int gear; /* Note how all the public methods are grouped together! */ public:     Bicycle() {     /* This is the constructor which initializes the variables */         cadence = 0;         speed = 0;         gear = 1;     }     void changeCadence(int newValue) {         cadence = newValue;     }     void changeGear(int newValue) {         gear = newValue;     }     void speedUp(int increment) {         speed = speed + increment;     }     void applyBrakes(int decrement) {         speed = speed - decrement;     }     void printStates() {         std::cout << "cadence:" << cadence << " speed:" << speed << " gear:" << gear << std::endl;     } }; #endif /* BICYCLE_H */
The member functions are effectively the same, but now we can deal with pointers! It has the cleanliness of Java with the low level-ness of C. NOTE NOTE NOTE that the class definition ends with a semicolon! This is really odd, strange, foreign, and outlandish to a Java programmer (it was for me anyways!). We create a main program main.cpp which is simply:
#include "Bicycle.h" int main() {     Bicycle bike;     bike.printStates();     return 0; }
Now, the command line when compiling this program, the command line reads: $ g++ --version g++ (GCC) 4.1.2 (Ubuntu 4.1.2-0ubuntu4) Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ g++ main.cpp $ ./a.out cadence:0 speed:0 gear:1 $ Which is exactly what we want, which is what we get if we program this in Java. Note if we were to make the constructor for the bicycle:
    Bicycle(int Cadence, int Speed, int Gear) {     /* This is the constructor which initializes the variables */         cadence = Cadence;         speed = Speed;         gear = Gear; }
We would have to modify the main.cpp code to be:
#include "Bicycle.h" int main() {     Bicycle bike(0,0,1); /* Note the difference from "= new Bicycle(0,0,1);" */     bike.printStates();     return 0; }
We end up having the same results.

Instantiating Objects

This next part was relatively odd for me. As a java/C#/D programmer, I am used to saying: Foo bar = new Foo(/* constructor arguments */);. In order to do this, we must create a pointer object: Foo *fooPointer = new Foo(/* arguments */); or else you simply construct a new object via lines like: Foo foo; without a constructor called at all. Perhaps I am approaching this the wrong way, and if I am any pointers (pun not intended, really) would be greatly appreciated!

On Inheritance

Consider the following foo.h header file that contains, logically as described by the approach above (of defining classes in independent header files), the foo class:
#ifndef FOO_H #define FOO_H #include < iostream > class foo { public:     virtual void sayHello()     {         std::cout << "foo says hello" << std::endl;     } };     #endif
The method must be virtual in order for us to take advantage of polymorphism. That is, if we have several lines of code like
foo *Bar = new bar(); Bar->sayHello();
What is printed out without the virtual quantifier is "foo says hello". With the virtual quantifier we invoke the bar class' sayHello() method. Now note the derived class bar in its respective bar.h header file:
#ifndef BAR_H #define BAR_H #include < iostream > #include "foo.h" //Note how this base header is included class bar : public foo /* This should be read as "public class bar extends foo" for you java programmers ;) */ { public:     void sayHello()     {         std::cout << "bar says hello" << std::endl;     } };         #endif
So we write the following main.cpp program that exploits our inheritance:
#include "foo.h" #include "bar.h" int main() {     foo var1;     bar var2;     var1.sayHello();     var2.sayHello();     return 0; }
Which prints out to the screen: $ g++ --version g++ (GCC) 4.1.2 (Ubuntu 4.1.2-0ubuntu4) Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ g++ main.cpp $ ./a.out foo says hello bar says hello $ There you have it!

Systems Programming

If you are like me, you are itching to start programming an operating system (even a toy one!) in C++ now that you know how to program C++ to be like Java. Well, there are some difficulties. These are outlined and overcome in a nice wiki page on Systems Programming at OSDev. Mainly one needs to over-ride the new() and delete() operators such that it calls kmalloc() and kfree():
//overload the operator "new"
void * operator new (uint_t size)
{
    return kmalloc(size);
}

//overload the operator "new[]"
void * operator new[] (uint_t size)
{
    return kmalloc(size);
}

//overload the operator "delete"
void operator delete (void * p)
{
    kfree(p);
}

//overload the operator "delete[]"
void operator delete[] (void * p)
{
    kfree(p);
}
Note this code is taken from the wiki.

Appendix

I decided to look up what some old fart C++ programmers had to say about Java in their comparison of the two languages. It was really interesting, perhaps even Enlightening, to say the least. One point they raised which I neglected was that every method has the virtual qualifier. On the one hand, this bloats the program; but on the other, it allows for every method to be over-ridden. Also, another issue that is raised is that in Java one can use the final qualifier in the following example:
final Rectangle r = new Rectangle(); r.side = 5; //Legal in Java
But in C++, one has to use const slightly differently:
const Rectangle r; r.side = 5; //ILLEGAL in C++
Just two different properties worthy of note. For a comparison of the try-catch-finally blocks, see this exerpt from the book Java in a Nutshell. For a comparison of the resource management, there was a technical paper which should be worthy of note.

No comments: