views:

81

answers:

3

I have the following code

#include <iostream>
#include <vector>

class Entity {
public:
    virtual void func() = 0;
};

class Monster : public Entity {
public:
    void func();
};

void Monster::func() {
std::cout << "I AM A MONSTER" << std::endl;
} 

class Buddha : public Entity {
public:
    void func();
};

void Buddha::func() {
std::cout << "OHMM" << std::endl;
}

int main() {
const int num = 5;  // How many of each to make
std::vector<Entity*> t;

for(int i = 0; i < num; i++) {
    Monster m;
    Entity * e;
    e = &m;

    t.push_back(e);
}

for(int i = 0; i < num; i++) {
    Buddha b;   
    Entity * e;
    e = &b;

    t.push_back(e);
}

for(int i = 0; i < t.size(); i++) {
    t[i]->func();
}

return 0;
}

However, when I run it, instead of each class printing out its own message, they all print the "Buddha" message. I want each object to print its own message: Monsters print the monster message, Buddhas print the Buddha message.

What have I done wrong?

+11  A: 

You need to allocate the objects from the heap with 'new'. What's happening here is that you're creating temporary objects, taking the pointer to those objects, and then those objects are being destroyed. Yes, this is differerent from many other languages. :)

Instead, try:

int main() {
   const int num = 5;  // How many of each to make
   std::vector<Entity*> t;

   for(int i = 0; i < num; i++) {
      Monster* m = new Monster;
      t.push_back(m);
   }

   for(int i = 0; i < num; i++) {
      Buddha* b = new Buddha;
      t.push_back(b);
   }

   for(int i = 0; i < t.size(); i++) {
      t[i]->func();
   }

   // This is very important!
   for(int i = 0; i < t.size(); i++) {
      delete t[i];
   }

   return 0;
}

When you see weird behavior like this, check to see the contents of the actual vector. You'd find that all of your slots had the same value, which is the spot on the stack that was holding the temporary monster then the temporary buddha.

dash-tom-bang
Thanks - that's perfect.
Ink-Jet
Mind that last loop that I added, too. Your `new`s must match your `delete`s.
dash-tom-bang
+1  A: 

What you have here is undefined behaviour - you can't store pointers to local variables in a vector with greater scope, as the variables will have evaporated by the time you come to call the virtual function on them. You will need to allocate the objects you are storing pointers to dynamically using new, and remember to free them with delete when you are done.

anon
+1  A: 

This happens because your m and b objects are local to their respective loops. After each iteration they go out of scope leaving the vector containing dangling pointers. In this case the behavior is undefined. Your program could very well have crashed.

P.S. Virtual inheritance is something entirely different.

Dima