指向基类的指针,调用虚函数的奇怪行为

时间:2010-05-13 21:55:55

标签: c++ inheritance pointers

我有以下代码

#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;
}

但是,当我运行它时,不是每个类都打印出自己的消息,而是打印出“佛”消息。我希望每个对象都能打印出自己的信息:怪物打印出怪物信息,佛像打印佛信息。

我做错了什么?

3 个答案:

答案 0 :(得分:13)

您需要使用'new'从堆中分配对象。这里发生的是你正在创建临时对象,将指针指向这些对象,然后这些对象被破坏。是的,这与许多其他语言不同。 :)

相反,请尝试:

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;
}

当你看到这样奇怪的行为时,请检查实际矢量的内容。你会发现你所有的老虎机都有相同的价值,这就是堆叠上持有临时怪物然后是临时大佛的位置。

答案 1 :(得分:2)

这是因为您的mb对象是各自循环的本地对象。每次迭代后,它们都会超出范围,从而使向量包含悬空指针。在这种情况下,行为是未定义的。你的程序很可能已经崩溃了。

P.S。 Virtual inheritance完全不同。

答案 2 :(得分:1)

你在这里有未定义的行为 - 你不能在具有更大范围的向量中存储指向局部变量的指针,因为变量将在你调用它们上面的虚函数时消失。您需要使用new动态分配存储指针的对象,并在完成后记得用delete释放它们。