Jump to content
xisto Community
qwijibow

More Advanced C++ Polymorphic / Abstract / Virtual example

Recommended Posts

This example assumes you already know basic c++ functions and classes.
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

#include<iostream>using namespace std;class base_class {public:[tab][/tab]void function1() {  cout << "function1 of base_class" << endl;[tab][/tab]}[tab][/tab]virtual void function2() {  cout << "function2 of base_class" << endl;[tab][/tab]}};class sub_class : public base_class {public:[tab][/tab]void function2() {  cout << "function2 of sub_class" << endl;[tab][/tab]}};class sub_class2 : public base_class {};int main() {[tab][/tab]base_class BASE;[tab][/tab]sub_class SUB_A;[tab][/tab]sub_class2 SUB_B;[tab][/tab]BASE.function1(); // outputs "function1 of base_class"[tab][/tab]BASE.function2(); // outputs "function2 of base_class"[tab][/tab][tab][/tab]SUB_A.function1(); // outputs "function1 of base_class"[tab][/tab]SUB_A.function2(); // outputs "function2 of sub_class"[tab][/tab][tab][/tab]SUB_B.function1(); // outputs "function1 of base_class"[tab][/tab]SUB_B.function2(); // outputs "function2 of base_class"[tab][/tab]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....
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

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++

class commom{};class tree : public common{};class bird : public common{};class car : public common{};class pan_galactic_gargle_blaster : public common{};int main() {[tab][/tab]common* array[5];[tab][/tab][tab][/tab]array[0] = new common;[tab][/tab]array[1] = new tree;[tab][/tab]array[2] = new bird;[tab][/tab]array[3] = new car;[tab][/tab]array[4] = new pan_galactic_gargle_blaster;[tab][/tab]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.
#include<iostream>#include<vector>using std::vector;using std::cout;using std::cin;

now we need our common base class
class shape {protected:[tab][/tab]int x_position;[tab][/tab]int y_position;[tab][/tab]int width;[tab][/tab]int height;public:[tab][/tab]virtual void draw() = 0;[tab][/tab]void setX(int x) {  x_position = x;[tab][/tab]}[tab][/tab]void setY(int y) {  y_position = y;[tab][/tab]}[tab][/tab]void setW(int w) {  width = w;[tab][/tab]}[tab][/tab]void setH(int h) {  height = h;[tab][/tab]}};

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/
class triangle : public shape {public:[tab][/tab]void draw() {[tab][/tab]  cout << "i am a triangle" << endl;  cout << "[tab][/tab]height:" << height << endl;  cout << "[tab][/tab]width:" << width << endl;  cout << "[tab][/tab]X:" << x_position << endl;  cout << "[tab][/tab]Y:" << y_position << endl;[tab][/tab]}};class circle : public shape {public:[tab][/tab]void draw() {[tab][/tab]  cout << "i am a circle" << endl;  cout << "[tab][/tab]radius:" << height << endl;  cout << "[tab][/tab]X:" << x_position << endl;  cout << "[tab][/tab]Y:" << y_position << endl;[tab][/tab]}};class rectangle : public shape {public:[tab][/tab]void draw() {[tab][/tab]  cout << "i am a rectangle" << endl;  cout << "[tab][/tab]height:" << height << endl;  cout << "[tab][/tab]width:" << width << endl;  cout << "[tab][/tab]X:" << x_position << endl;  cout << "[tab][/tab]Y:" << y_position << endl;[tab][/tab]}};class dot : public shape {public:[tab][/tab]void draw() {[tab][/tab]  cout << "i am a dot" << endl;  cout << "[tab][/tab]X:" << x_position << endl;  cout << "[tab][/tab]Y:" << y_position << endl;[tab][/tab]}};

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.

int main() {[tab][/tab]vector<shape*> shapes;[tab][/tab]shapes.push_back( new triangle() );[tab][/tab]shapes.push_back( new circle() );[tab][/tab]shapes.push_back( new rectangle() );[tab][/tab]shapes.push_back( new dot() );[tab][/tab]shapes.push_back( new triangle() );[tab][/tab]shapes.push_back( new circle() );[tab][/tab]shapes.push_back( new rectangle() );[tab][/tab]shapes.push_back( new dot() );[tab][/tab]// set all the shapes member variables (idealy, use random)[tab][/tab]for(int n=0; n< shapes.size(); n++) {  shapes[n]->setX(1);  shapes[n]->setY(2);  shapes[n]->setH(3);  shapes[n]->setW(4);[tab][/tab]}[tab][/tab]// draw the picture ![tab][/tab]for(int n=0; n< shapes.size(); n++) {  shapes[n]->draw();[tab][/tab]}[tab][/tab]       // clean up, prevent memory leaks.[tab][/tab]for(int n=0; n< shapes.size(); n++) {  delete shapes[n];[tab][/tab]}[tab][/tab]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.

bash-2.05b$ g++ TEST.cpp -o TESTbash-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 ?

Share this post


Link to post
Share on other sites

Wow, great tutorial. I couldn't find any good tutorials yet, so I stopped trying to find good C++ resources on the net and focust on books and things. I must say I realy like this one. Could you also write us a tutorial about game programming in C++? Then I realy would be delighted ;).-=jeroen=-

Share this post


Link to post
Share on other sites

Could you also write us a tutorial about game programming in C++

I can do the next best thing...
Post a link to a great game programming tutorial.

(well, not really a game programming tutorial, its an OpenGL tutorial, that uses games as its example programs. but still very good)

http://nehe.gamedev.net/

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

Terms of Use | Privacy Policy | Guidelines | We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.