it is by no means a complete c++ tutorial, but should give you a good idea of the power of c++.
In this tutorial, i will be using virtualisation, abstraction, and polymorphism to draw a simple picture.
the code is not complete, because i dont want to tie it into any specific operating system.
i will use onlt standard template library finctions, and graphics requires the use of OS specific API's/
We are going to write a program, which holds an array or different shapes.
and (if complete) would draw thenm ot the screen.. (for this example, the will just output somthing like "I am a circle, radius 12, x=20, y=50"
It doesnt sound impressive, but we will be using a single array to hold different classes without using a container. In other words, its like having an array that holds some integers, some booleans, and some strings. it is normally not allowed.
first, before the code, some simple definitions.
=============================
Virtual functions:
=============================
A virtual function is a function which apears to exist to some parts of the code, but aprears not to exist to other parts of the code.
a Pure virtual function is the same, but has no function body. if a class has at least one pure virtual function, then it is considered abstract. meaning it cannot be used directly, but can be used as a template for other functions.
Take a look at the following example program
CODE
#include<iostream>
using namespace std;
class base_class {
public:
void function1() {
cout << "function1 of base_class" << endl;
}
virtual void function2() {
cout << "function2 of base_class" << endl;
}
};
class sub_class : public base_class {
public:
void function2() {
cout << "function2 of sub_class" << endl;
}
};
class sub_class2 : public base_class {};
int main() {
base_class BASE;
sub_class SUB_A;
sub_class2 SUB_B;
BASE.function1(); // outputs "function1 of base_class"
BASE.function2(); // outputs "function2 of base_class"
SUB_A.function1(); // outputs "function1 of base_class"
SUB_A.function2(); // outputs "function2 of sub_class"
SUB_B.function1(); // outputs "function1 of base_class"
SUB_B.function2(); // outputs "function2 of base_class"
return 0;
}
virtual function2 in the base class apears to exist, except to the class sub_class, because this class defines its own function2, it over-rides the virtual function.
we could have made function2 a pure virtual function be declairing it like so....
CODE
virtual void function2() = 0;
a pure virtual function exists ONLY to be over-ridden.
you cannot declair an instance of a class containing pure virtual functions, and so if this had been the case, the line
CODE
base_class BASE;
would have caused a compile error.a class containing pure virtual functions is called abstract.
=============================
Polymorphic objects. (the clever pointer)
=============================
In C++, the pointer rules have been relaxed.
a pointer of type XYZ can point to any class derived from XYZ
the following code example is perfectly legal in c++
CODE
class commom{};
class tree : public common{};
class bird : public common{};
class car : public common{};
class pan_galactic_gargle_blaster : public common{};
int main() {
common* array[5];
array[0] = new common;
array[1] = new tree;
array[2] = new bird;
array[3] = new car;
array[4] = new pan_galactic_gargle_blaster;
return 0;
}
=====================================================
MAIN example, combining the 2 examples above.
======================================================
Armed with the ability to have an array of different types, and the ability to over ride functions,
we can do some very clever things.
we are going to write a simpe drawing program.
it will be an array of different shapes, the base class will have a draw() function
which draws different shapes, depending on how it is used. (polymorphic, to change shape! lol )
// include the usual stuff.
CODE
#include<iostream>
#include<vector>
using std::vector;
using std::cout;
using std::cin;
now we need our common base class
CODE
class shape {
protected:
int x_position;
int y_position;
int width;
int height;
public:
virtual void draw() = 0;
void setX(int x) {
x_position = x;
}
void setY(int y) {
y_position = y;
}
void setW(int w) {
width = w;
}
void setH(int h) {
height = h;
}
};
This is ab abstract class because it contains a pure virtual function draw.
the size variables, and manipulation functions are common to all shapes, so they go in the base class.
now lets add some shapes/
CODE
class triangle : public shape {
public:
void draw() {
cout << "i am a triangle" << endl;
cout << " height:" << height << endl;
cout << " width:" << width << endl;
cout << " X:" << x_position << endl;
cout << " Y:" << y_position << endl;
}
};
class circle : public shape {
public:
void draw() {
cout << "i am a circle" << endl;
cout << " radius:" << height << endl;
cout << " X:" << x_position << endl;
cout << " Y:" << y_position << endl;
}
};
class rectangle : public shape {
public:
void draw() {
cout << "i am a rectangle" << endl;
cout << " height:" << height << endl;
cout << " width:" << width << endl;
cout << " X:" << x_position << endl;
cout << " Y:" << y_position << endl;
}
};
class dot : public shape {
public:
void draw() {
cout << "i am a dot" << endl;
cout << " X:" << x_position << endl;
cout << " Y:" << y_position << endl;
}
};
each class needs to override the pure virtual function in the shape class.
if a class failed to override the draw() function, then that class would in turn become abstract.
finally, let se out super cool porgram in action.
CODE
int main() {
vector<shape*> shapes;
shapes.push_back( new triangle() );
shapes.push_back( new circle() );
shapes.push_back( new rectangle() );
shapes.push_back( new dot() );
shapes.push_back( new triangle() );
shapes.push_back( new circle() );
shapes.push_back( new rectangle() );
shapes.push_back( new dot() );
// set all the shapes member variables (idealy, use random)
for(int n=0; n< shapes.size(); n++) {
shapes[n]->setX(1);
shapes[n]->setY(2);
shapes[n]->setH(3);
shapes[n]->setW(4);
}
// draw the picture !
for(int n=0; n< shapes.size(); n++) {
shapes[n]->draw();
}
// clean up, prevent memory leaks.
for(int n=0; n< shapes.size(); n++) {
delete shapes[n];
}
return 0;
}
the vector MUST be a vector of pointers to shapes, and not a vector of shapes.
the the intelligent pointer that knows what functions to call.
and just for fun, the output of the compiled program.
QUOTE
bash-2.05b$ g++ TEST.cpp -o TEST
bash-2.05b$ ./TEST
i am a triangle
height:3
width:4
X:1
Y:2
i am a circle
radius:3
X:1
Y:2
i am a rectangle
height:3
width:4
X:1
Y:2
i am a dot
X:1
Y:2
i am a triangle
height:3
width:4
X:1
Y:2
i am a circle
radius:3
X:1
Y:2
i am a rectangle
height:3
width:4
X:1
Y:2
i am a dot
X:1
Y:2
bash-2.05b$ ./TEST
i am a triangle
height:3
width:4
X:1
Y:2
i am a circle
radius:3
X:1
Y:2
i am a rectangle
height:3
width:4
X:1
Y:2
i am a dot
X:1
Y:2
i am a triangle
height:3
width:4
X:1
Y:2
i am a circle
radius:3
X:1
Y:2
i am a rectangle
height:3
width:4
X:1
Y:2
i am a dot
X:1
Y:2
Even advanced C++ isnt too complicated when you understand whats happening.
Any questions / comments / surgestions ?

