错误消息:不允许抽象类类型为“X”的对象:纯虚拟“Y”没有覆盖

时间:2018-04-27 00:23:10

标签: c++

Enemy.h

class Enemy
{
    int hp;
public:
    Enemy(int);
    void setHP(int);
    int getHP();
    virtual int attack() = 0;
};

Enemy.cpp

Enemy::Enemy(int playerXP)
{
    if (playerXP == 0) {
        hp = rand() % 5 + 1;
    }
    else if (playerXP > 0) {
        hp = rand() % (playerXP * 5) + 1;
    }
}

void Enemy::setHP(int currentHP)
{
    hp = currentHP;
}

int Enemy::getHP()
{
    return hp;
}

Reaper.h

#pragma once
#include "Enemy.h"

class Reaper : public Enemy
{
public:
    Reaper(int playerXP) : Enemy(playerXP)
    {   
    }

    int attack(int, int);
};

Reaper.cpp

int Reaper::attack(int pa, int php)
{
    int eatk = 0;
    if (pa == 0) {
        eatk = php * .5;
    }
    else {
        eatk = rand() % php * .25;
    }
    return eatk;
}

错误:

  

不允许使用抽象类类型“Reaper”的对象:   纯粹的虚拟功能“敌人:攻击”没有覆盖。

我的问题是..为什么我收到此错误?我试图理解为什么我会得到这个,以及任何可能的答案来解决它。

2 个答案:

答案 0 :(得分:5)

Reaper是抽象的,因为它不是覆盖抽象Enemy::attack()方法,而是重载。因此,您无法直接创建Reaper的任何对象实例。

当派生类想要覆盖基类的虚方法时,派生方法必须与它覆盖的基本方法具有相同的签名。这意味着它具有相同的返回类型(或至少是兼容的covariant return type),调用约定,参数列表和常量。

Reaper::attack()的参数列表与Enemy::attack()不同。这就是Reaper::attack()重载而不是覆盖的原因。

在C ++ 11及更高版本中,您可以(并且应该)使用新的override keyword标记Reaper::attack(),例如:

class Reaper : public Enemy
{
public:
    ...    
    int attack(int, int) override;
};

这样,编译器将采取额外的步骤来验证兼容的基本方法是否确实存在,如果没有找到,那么它将发出更有意义的错误消息。例如,this live demo在使用override时会产生这些错误,如上所示:

prog.cpp:41:9: error: ‘int Reaper::attack(int, int)’ marked ‘override’, but does not override
     int attack(int, int) override;
         ^~~~~~
prog.cpp: In function ‘int main()’:
prog.cpp:57:9: error: cannot declare variable ‘r’ to be of abstract type ‘Reaper’
  Reaper r(0);
         ^
prog.cpp:34:7: note:   because the following virtual functions are pure within ‘Reaper’:
 class Reaper : public Enemy
       ^~~~~~
prog.cpp:11:17: note:   virtual int Enemy::attack()
     virtual int attack() = 0;
                 ^~~~~~

答案 1 :(得分:4)

编译器没有意识到你想要覆盖基类中的攻击函数。它将int attack()int attack(int, int)视为两个不同的函数,因为它们具有不同的类型签名。结果是你的Reaper类有两个函数,其中一个是纯虚函数。使用override关键字可以帮助避免这些错误,尽管它仅在C ++ 11及更高版本中可用。