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:
Post a Comment