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”的对象: 纯粹的虚拟功能“敌人:攻击”没有覆盖。
我的问题是..为什么我收到此错误?我试图理解为什么我会得到这个,以及任何可能的答案来解决它。
答案 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及更高版本中可用。