Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » C++ array of different classes

Credits go to kazzmir for helping out!
This thread is locked; no one can reply to it. rss feed Print
C++ array of different classes
William Labbett
Member #4,486
March 2004
avatar

hi,

with C++, I've been learning about base and derived classes.

Is it possible to declare a vector of the base class and then push different
classes which are all derived from it into the vector ?

so that later on, you could run through the vector and call a virtual function for all the objects ?

kazzmir
Member #1,786
December 2001
avatar

Yes.

William Labbett
Member #4,486
March 2004
avatar

vector<BaseClassName> v;

/* class Archer */ Archer archer;

/* class Swordsman */ Swordsman swordsman;

archer = Archer(10,2, 100);
swordsman = Swordsman(30, 40, 2);

v.push_back(archer);
v.push_back(swordsman);

Is it as simple as that ?

kazzmir
Member #1,786
December 2001
avatar

You have to use pointers.

vector<BaseClassName*> v;
Archer * archer = new Archer();
Swordsman * swordsman = new Swordsman();
v.push_back(archer);
v.push_back(swordsman);

When you go to get the elements back out they will have the type BaseClassName instead of Archer or SwordsMan. Its possible to down cast the elements to their true type but usually thats bad programming practice.

William Labbett
Member #4,486
March 2004
avatar

I see. That makes sense. Thanks for that :)

/* EDIT */

Trying to compile a base class and a derived class and I'm getting this :

echo :
:
echo : compiling polygon.cpp
: compiling polygon.cpp
echo :
:
g++ -c polygon.cpp -o polygon.o
echo :
:
echo building pong_game.exe
building pong_game.exe
echo
ECHO is off.
g++ -o pong_game.exe pong_main.o one_game.o ball.o bat.o bitmap_list.o polygon.o
-static-libgcc -static-libstdc++ -lallegro-5.0.4-monolith-mt
polygon.o:polygon.cpp:(.text$_ZN12LevelFeatureC2Ev[LevelFeature::LevelFeature()]
+0x8): undefined reference to `vtable for LevelFeature'
collect2: ld returned 1 exit status
mingw32-make: *** [pong_game.exe] Error 1
press a key

Here's the code :

class LevelFeature {


   protected:
      LevelFeature() {}
    
   public:
      virtual void draw() const;
      virtual void update();

    
    
};

#SelectExpand
1#include "level_feature.h" 2 3 4 5 6 7 8struct Point { 9 float x, y; 10}; 11 12 13 14 15class Polygon : LevelFeature { 16 17 18 int number_of_sides; 19 20 float angle; 21 22 float increment_angle; 23 24 int cx, cy; /* centre x, centre y */ 25 26 float radius_to_vertex; 27 28 Point *vertices; 29 30 int direction_of_spin; 31 32 ALLEGRO_COLOR polygon_color; 33 34public: 35 36 Polygon(int cx, int cy, int number_of_sides, float r, float ic, int direction_of_spin, ALLEGRO_COLOR c); 37 38 void draw() const; 39 40 void update(); 41 42 43 44 45};

#SelectExpand
1 2#include <cmath> 3 4#include "polygon.h" 5 6 7 8 9Polygon::Polygon(int cx, int cy, int sides, float r, float ic, int direction_of_spin, ALLEGRO_COLOR c) 10 11 : cx(cx), cy(cy), number_of_sides(sides), radius_to_vertex(r), direction_of_spin(direction_of_spin), increment_angle(ic) 12 13{ 14 15 16 int vn; /* vertex number */ 17 18 float a; /* angle */ 19 20 vertices = new Point [sides]; 21 22 for(vn = 0; vn < number_of_sides; ++vn) 23 { 24 25 /* Get the angle to the vertex. */ 26 27 a = (( 2.0f * ALLEGRO_PI ) / number_of_sides) * (float) vn; 28 29 vertices[vn].x = radius_to_vertex * cos(a); 30 vertices[vn].y = radius_to_vertex * sin(a); 31 32 } 33 34 polygon_color = c; 35 36 37}; 38 39 40 41 42 43void Polygon::update() 44{ 45 if(direction_of_spin == 0) 46 { 47 angle += increment_angle; 48 49 if(angle > ALLEGRO_PI * 2.0f) 50 { 51 angle -= ALLEGRO_PI * 2.0f; 52 } 53 } 54 else 55 { 56 angle -= increment_angle; 57 58 if(angle < 0.0f) 59 { 60 angle = ALLEGRO_PI * 2.0f + angle; 61 } 62 } 63 64 int vn; 65 66 float a; 67 68 for(vn = 0; vn < number_of_sides; ++vn) 69 { 70 71 /* Get the angle to the vertex. */ 72 73 a = (( 2.0f * ALLEGRO_PI ) / number_of_sides) * (float) vn + angle; 74 75 if(angle > ALLEGRO_PI * 2.0f) 76 { 77 angle -= ALLEGRO_PI * 2.0f; 78 } 79 80 vertices[vn].x = radius_to_vertex * cos(a); 81 vertices[vn].y = radius_to_vertex * sin(a); 82 } 83 84}; 85 86 87 88void Polygon::draw() const 89{ 90 int vn; 91 92 for(vn = 0; vn < number_of_sides - 1; ++vn) 93 { 94 al_draw_filled_triangle( cx, cy, vertices[vn].x, vertices[vn].y, vertices[vn + 1].x, vertices[vn + 1].y, polygon_color); 95 } 96 97 al_draw_filled_triangle( cx, cy, vertices[number_of_sides].x, vertices[number_of_sides].y, vertices[0].x, vertices[0].y, polygon_color); 98}

Any ideas ?

Edgar Reynaldo
Member #8,592
May 2007
avatar

You haven't implemented one of the virtual functions that you declared. Since you defined both draw and update in your Polygon class, that leaves the base class. Either make the base class functions 'pure virtual' by adding '=0' between the closing paranthesis and the semicolon, or define those functions in the base class.

William Labbett
Member #4,486
March 2004
avatar

Ah, Edgar to the rescue!

Thanks. I understand now.

I think I need to keep on with the book I've got because it's due to lack of doing the execises thoroughly that's leaving me having to ask all these questions.

I remember when you said something about "If you find code that's more concise and easy to read, less preferable than C, then so be it.", when I said I thought I wouldn't learn C++.

Albeit slowly, I'm getting to grips with it now eh?

Thanks.

Oscar Giner
Member #2,207
April 2002
avatar

kazzmir said:

Its possible to down cast the elements to their true type but usually thats bad programming practice.

It's not possible to do that, since the vector only stores copies of the original objects, and they're converted to the base class (all data of the derived classes is lost in the copy).

kazzmir
Member #1,786
December 2001
avatar

vector<Base*> all;
all.push_back(new Derived());
Derived * d = (Derived*) all[0];

Oscar Giner
Member #2,207
April 2002
avatar

Ah for some reason I though you meant having a vector of values, not of pointers.

taronĀ 
Member #10,584
January 2009
avatar

With typeid it's also possible to know at runtime, what type an object is, but this is even more likely to be bad programming practice than downcasting is.

SiegeLord
Member #7,827
October 2006
avatar

taronĀ  said:

With typeid it's also possible to know at runtime, what type an object is, but this is even more likely to be bad programming practice than downcasting is.

Might as well use dynamic_cast then.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Edgar Reynaldo
Member #8,592
May 2007
avatar

Go to: