4

I have two classes:

class Object {
public:
  Object();
  virtual void update();
  virtual void draw();

private:

protected:
  int x, y, tick;

}

and

class Unit : public Object {
public:
  Unit();
  void update();

private:

protected:

}

I then define the constructors and functions in sepparate .cpp files.

Here's the definitions for Object:

Object::Object() {
  x = y = 0;
};

Object::update() {
  tick ++;
};

Object::draw() {
  // All my draw code is in here.
};

And Unit:

Unit::Unit() : Object() {

};

Unit::update() {
  Object::update();
  // Then there's a bunch of movement related code here.
};

Everything works fine individually, but I run into a problem when trying to call functions from within a vector.

vector<Object> objects;

I then do this in my void main():

for (int i = 0; i < objects.size(); i ++) {
  objects[i].update();
  objects[i].draw();
};

This draws everything fine, but it only calls the Object verson of update() not the version as defined by the derived class. Do I have to make a vector for each type that I derive from the Object class for it to work, or is there another way to call the derived functions?

Thanks in advance - Seymore

Seymore
  • 43
  • 1
  • 3
  • You shouldn't be doing anything in your *void main()*. The correct signature is *int main()*. Yes, your compiler probably happily accepts *void* as a return type, but it is still a good idea to use the correct signature as required by the C++ Standard, especially if you're new to the language and trying to learn it. – decltype Mar 11 '11 at 10:01

2 Answers2

6

Yes, it calls methods of class Object, because you have a vector of class Object objects:

vector<Object> objects; // stores instances of class Object

The possible solution is to use a vector of pointers:

vector<Object*> objects;
objects.push_back( new Unit() );

and then call though pointers:

for (int i = 0; i < objects.size(); i ++) {
    objects[i]->update();
    objects[i]->draw();
}
sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • Wow. I didn't expect such a fast answer. This solved my problem as far as I can tell. Thank you very much. – Seymore Mar 11 '11 at 08:42
  • 2
    @Seymore: You're welcome and don't forget to take care of those objects created with `new` later. – sharptooth Mar 11 '11 at 08:50
  • What about if I'm using an already instantiated object? Like: SubObject sub; vector objects; objects.push_back(sub);Then do I need a smart ptr? – Aaron H. Jul 29 '14 at 18:43
  • @AaronH.: You'd better not use one here, because the smart ptr destructor will destroy the object, then the object's destructor will be run again which will lead to undefined behavior. – sharptooth Jul 30 '14 at 07:30
2

If you want to use object oriented polymorphism in C++ (with the meaning : you have a base class and derived classes and at runtime you can come across any off those) you must use pointers.

vector<Object *> objects;

That means manual memory management (but you can use shared_pointers or http://www.boost.org/doc/libs/1_35_0/libs/ptr_container/doc/ptr_container.html), and possibly a very slight loss of performance (because of one extra dereferencing and v-table, however you shouldn't really care about it). And don't forget to make your methods virtual ;)

I think this is why I rarely use on my daily work object oriented programming as I learned it at school ;) I use heritage, but don't mix mother and daugther classes in the same containers (and I use templates for many interfaces).

Tristram Gräbener
  • 9,601
  • 3
  • 34
  • 50