虚拟功能无法正常运行

时间:2011-05-08 23:54:30

标签: c++ oop destructor virtual-functions

  

可能重复:
  class has virtual functions and accessible non-virtual destructor

我从thenewboston的教程中得到了这段代码:

#include <iostream>

using namespace std;

class Enemy {
public:
    virtual void attack(){};
};

class Ninja: public Enemy {
public:
    void attack(){
        cout << "ninja attack"<<endl;
    }
};

class Monster: public Enemy {
public:
    void attack(){
        cout << "monster attack"<<endl;
    }
};

int main() {
    Ninja n;
    Monster m;
    Enemy * enemy1 = &n;
    Enemy * enemy2 = &m;
    enemy1->attack();
    enemy2->attack();
    cin.get();
    return 0;
}

为什么我会收到这些警告:

class Enemy has virtual functions and accessible non-virtual destructor
class Ninja has virtual functions and accessible non-virtual destructor
class Monster has virtual functions and accessible non-virtual destructor

2 个答案:

答案 0 :(得分:4)

编译器只是警告您,派生类的析构函数(由编译器添加)不是虚拟的。在这种情况下,没有问题,你可以忽略警告。但是当你的派生类获得需要在析构函数中正确释放的其他数据元素时,你需要使析构函数成为虚拟,所以它们会在Enemy指针上使用delete调用(否则只会调用Enemy析构函数)。

编辑:当然,您不必在派生类的定义中将析构函数设置为虚拟,而是在基类中(或者为了清晰起见)。

答案 1 :(得分:2)

您的编译器正在敦促您为三个类添加虚拟析构函数。在这个特定情况下,它并不重要,但对于任何可以多态使用的类都有一个虚拟析构函数通常是个好主意。

考虑以下示例:

class Fight
{
public:
    Fight(Player* player, Enemy* enemy)
    {
        m_player = player;
        m_enemy  = enemy;
    }

    void playerAttack()
    {
        m_player.attack(m_enemy);
        if (m_enemy.isDead())
            delete m_enemy;
    }

private:
    Player* m_player;
    Enemy* m_enemy;
}

这里删除指向Enemy-instance的指针,该实例可能是派生类。派生类可能有自己的额外数据成员(在Enemy的数据成员之上)或特殊的初始化代码,但如果Enemy及其子类具有虚拟析构函数,delete只能访问此代码。否则,它将运行Enemy的析构函数,这可能会导致非常糟糕的结果。

请注意,在您的代码中,Monster和Ninja只能在堆栈上分配,并且它们不需要虚拟析构函数(因为编译器在编译时知道每个对象的完整类型)。但实际上,动态分配多态对象(即具有公共虚函数的类的实例)是很常见的。因此,作为规则,您应该将虚拟析构函数添加到此类类中。