【问题标题】:How to properly use virtual member functions in c++如何在 C++ 中正确使用虚成员函数
【发布时间】:2012-04-19 14:08:12
【问题描述】:

下面的代码有问题,被覆盖的虚函数没有执行。不确定我在这里做错了可能是一个愚蠢的错误。无论如何,这是一个游戏项目,我有一个看起来像这样的对象数组(core::array 是一个 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

【问题讨论】:

  • 如果将 void Zombie::shot(int) 声明为虚拟会发生什么?你用的是什么编译器?
  • 我正在使用visual express c++,我尝试在派生中使用虚函数,但它不起作用,我怀疑它正在分割下面答案中给出的内容
  • @DannyBirch:在派生类中使用virtual 关键字并没有什么不同,如果您愿意,也可以省略它。重要的是它是基类中的virtual

标签: c++ oop virtual


【解决方案1】:

我怀疑您正在经历切片,因为 gameTargets 数组包含值。我不能确定,因为我不知道core::array 模板是如何工作的。有关什么是切片的讨论,请参阅 What is object slicing?

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

core::array<GameObject *> gameTargets;

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

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

【讨论】:

  • 好的,我看看切片。谢谢!
【解决方案2】:

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

在不确切知道您的 core::array 做什么的情况下,我怀疑您真正想要创建的是一个 std::unique_ptr&lt;GameObject&gt;(智能指针)数组,类似于

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

【讨论】:

    【解决方案3】:

    一种快速的解决方案是将这些父函数设为纯虚函数,如下所示:

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

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

    【讨论】:

    • 我认为这不会解决任何问题;事实上,代码甚至可能不再编译,因为 core::array&lt;GameObject&gt; 类型不能再被实例化,因为 GameObject 由于纯虚方法是抽象的。
    • 是的,这就是我需要编辑帖子的原因;我假设他持有指针数组......(不知道我是如何错过数组中丢失的指针)
    猜你喜欢
    • 2019-09-09
    • 2014-10-03
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    • 1970-01-01
    • 2015-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多