简体   繁体   English

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

[英]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? 我做错了什么?

You need to allocate the objects from the heap with 'new'. 您需要使用“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. 你会发现你所有的老虎机都有相同的价值,这就是堆叠上持有临时怪物然后是临时大佛的位置。

This happens because your m and b objects are local to their respective loops. 发生这种情况是因为mb对象是各自循环的本地对象。 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. 你的程序很可能已经崩溃了。

PS Virtual inheritance is something entirely different. PS 虚拟继承是完全不同的东西。

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. 您将需要使用new动态分配要存储指针的对象,并在完成后记得使用delete它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM