如何在c ++中正确使用虚拟成员函数

时间:2012-04-19 14:08:13

标签: c++ oop virtual

我遇到以下代码的问题,覆盖的虚拟函数没有执行。不确定我在这里做错了可能是一个愚蠢的错误。无论如何这是一个游戏项目,我有一个看起来像这样的对象数组(核心::数组是一个irrlicht数组,类似于向量数组)

core::array<GameObject> gameTargets;

这是GameObjectZombie定义

class GameObject {
protected:
    scene::ISceneNode* node;
public:
    int ID;
    int hitpoints;

    GameObject() {
        ...
    };

    void setNode(scene::ISceneNode* inode) {
        ...
    }

    virtual void shot(int dmg) {
        ... [BREAKPOINT HERE]
    }

    scene::ISceneNode* getNode() {
        return node;
    }
};

class Zombie : public GameObject {
public:
    static const enum Animation {
        ZOMBIE_WALK,
        ZOMBIE_HURT,
        ZOMBIE_DIE,
        ZOMBIE_TWITCH,
        ZOMBIE_ATTACK,
        ZOMBIE_IDLE
    };

    //We only want to accepted animated mesh nodes for this object
    Zombie(int hp, scene::IAnimatedMeshSceneNode* inode) {
        ...
    }

    //Override the shot function
    void shot(int dmg) {
        ... [BREAKPOINT HERE]
    }

    //Animate the zombie
    void setAnimation(Animation anim) {
        ...
    }
};

永远不会调用派生类的成员函数,我正在创建像这样的对象

Zombie target(hp, (scene::IAnimatedMeshSceneNode*)node);

并像这样调用虚拟函数

for(int i = 0; (u32)i<level->gameTargets.size(); i++) {
    if(selectedNode == level->gameTargets[i].getNode()) {
        level->gameTargets[i].shot(b->damage);
    }
}

其中b是指向具有int变量伤害的子弹的指针,gameTargets包含GameObject

3 个答案:

答案 0 :(得分:7)

我怀疑你正在经历切片,因为gameTargets数组包含值。我无法确定,因为我不知道core::array模板的工作原理。有关切片的讨论,请参阅What is object slicing?

要解决此问题,请将原始指针存储在

core::array<GameObject *> gameTargets;

或使用某种引用计数指针,如

core::array<std::shared_ptr<GameObject>> gameTargets; // only available in C++11

答案 1 :(得分:1)

array<GameObject>是一个对象的容器,而不是一个指针容器。您添加到它的每个对象都是GameObject而不是派生类之一(如果您添加派生类对象,那么它将被“切片”)。

如果不确切知道你的core::array做了什么,我怀疑你真正打算创建的是std::unique_ptr<GameObject>(智能指针)的数组

core::array< std::unique_ptr<GameObject> > gameTargets;
std::unique_ptr<GameObject> my_zombie(new Zombie);
gameTargets.push_back( my_zombie );

答案 2 :(得分:0)

快速解决方案是将这些父函数作为纯虚函数,如:

virtual void shot(int dmg) { } = 0; 

//编辑 并使用Frerich Raabe建议的指针数组