首页 > 解决方案 > 错误消息:不允许抽象类类型“X”的对象:纯虚拟“Y”没有覆盖器

问题描述

敌人.h

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

敌人.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;
}

收割者.h

#pragma once
#include "Enemy.h"

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

    int attack(int, int);
};

收割者.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”的对象:纯虚函数“Enemy:attack”没有覆盖器。

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

标签: c++

解决方案


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

当派生类想要重写基类的虚方法时,派生方法必须具有与其重写的基方法相同的签名。这意味着它具有相同的返回类型(或至少兼容的协变返回类型)、调用约定、参数列表和常量。

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

在 C++11 及更高版本中,您可以(并且应该)Reaper::attack()使用 newoverride关键字进行标记,例如:

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

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

prog.cpp:41:9: 错误:'int Reaper::attack(int, int)' 标记为'覆盖',但不覆盖
     int 攻击(int,int)覆盖;
         ^~~~~~
prog.cpp:在函数'int main()'中:
prog.cpp:57:9:错误:不能将变量“r”声明为抽象类型“收割者”
  收割者 r(0);
         ^
prog.cpp:34:7: 注意:因为以下虚函数在'Reaper'中是纯的:
 类收割者:公共敌人
       ^~~~~~
prog.cpp:11:17:注意:虚拟 int Enemy::attack()
     虚拟int攻击()= 0;
                 ^~~~~~

推荐阅读