Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vector of pointers to base class, odd behaviour calling virtual functions

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?

like image 460
Joseph Salisbury Avatar asked May 23 '26 11:05

Joseph Salisbury


2 Answers

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.

like image 82
dash-tom-bang Avatar answered May 26 '26 00:05

dash-tom-bang


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.

like image 30
Dima Avatar answered May 26 '26 02:05

Dima



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!