Q:

Error message: Object of abstract class type "X" is not allowed: Pure virtual "Y" has no overrider

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;
}

Error:

Object of abstract class type "Reaper" is not allowed: 
  Pure virtual function "Enemy:attack" has no overrider.

My question is.. Why am I getting this error?  I'm trying to understand why I am getting this, and also any possible answers to solve it.

A:

Reaper is abstract because it is not overriding the abstract Enemy::attack() method, it is overloading it instead.  As such, you cannot create any object instances of Reaper directly.
When a derived class wants to override a virtual method of a base class, the derived method MUST have the same signature as the base method it is overriding.  That means it has the same return type (or at least a compatible covariant return type), calling convention, parameter list, and constness.
Reaper::attack() has a different parameter list than Enemy::attack().  That is why Reaper::attack() is an overload instead of an override.
In C++11 and later, you can (and should) mark Reaper::attack() with the new override keyword, eg:
class Reaper : public Enemy
{
public:
    ...    
    int attack(int, int) override;
};

That way, the compiler will take extra steps to verify whether a compatible base method actually exists, and if none is found then it will issue more meaningful error messages.  For example, this live demo produces these errors when using override as shown above:

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;
                 ^~~~~~

A:

The compiler doesn't realize that you want to override the attack function in the base class. It sees int attack() and int attack(int, int) as two different functions because they have different type signatures. The result is that your Reaper class has two functions, one of which is a pure virtual function. Using the override keyword can help to avoid these errors, although it is only available in C++11 and newer.

