I want to pass a member method as an argument to another member method. I have researched this extensively but still can not see to get it correct. My header file is as follows
#include <string>
#include <map>
#include <functional>
#include "Entity.h"
#include "World.h"
#include "Item.h"
class Tile;
class Player : public Entity
{
private:
using FunctionPointer = void (Player::*)(Tile*);
bool victory;
Point location;
std::map<char, FunctionPointer> actions;
public:
Player(std::string name, int gold, int maxHitPoints, int defensePoints,
Point startingLocation, int maxDamage = 0, int maxItems = -1,
std::vector<Item*> inventory = std::vector<Item*>());
std::string getClassName() const override;
void printInventory(Tile*) override;
std::string toString() override;
Point getLocation() const;
Item* findMostPowerfulWeapon();
void heal(Tile*);
void moveNorth(Tile*);
void moveSouth(Tile*);
void moveEast(Tile*);
void moveWest(Tile*);
void attack(Tile* tile);
void pickup(Tile* tile);
void trade(Tile* tile);
void getAvailableActions(Tile* tile);
void chooseAction();
private:
void move(int dx, int dy);
void actionAdder(char hotkey, FunctionPointer, std::string name);
};
And a part of the cpp file that is giving me problems is as follows:
void Player::getAvailableActions(Tile * tile)
{
actions.clear();
std::cout << "Choose an action:" << std::endl;
if (getInventory().size() > 0)
actionAdder('i', (this->*(&Player::printInventory))(tile), "Print inventory");
if (tile->getClassName() == "Trader")
actionAdder('t', (this->*(&Player::trade))(tile) , "Trade");
if (tile->getClassName() == "Monster")
actionAdder('a', (this->*(&Player::attack))(tile), "Attack");
}
void Player::actionAdder(char hotkey, FunctionPointer action, std::string name)
{}
Visual studio marks the parenthesis in front of all three this, (this->*(&Player::attack))(tile), and gives the tool tip "argument of type "void" is incompatible with parameter of type "Player::FunctionPointer"". The compiler error that I get if I try to compile is 'void Player::actionAdder(char,Player::FunctionPointer,std::string)': cannot convert argument 2 from 'void' to 'Player::FunctionPointer'.
If anyone has any idea of what I am doing wrong I would be grateful for any suggestions. If you need to see more code or more details let me know. The code is not super secret.
Thanks
Read the error messages carefully:
argument of type "
void
" is incompatible with parameter of type
and
cannot convert argument 2 from '
void
' to 'Player::FunctionPointer
'.
That's because argument 2 here:
actionAdder('i', (this->*(&Player::printInventory))(tile), "Print inventory");
is actually invoking printInventory
and trying to pass the result of that invocation into actionAdder()
. But that's a void
function, and you can't pass something of type void
to something else - hence the error complaining about precisely that.
You don't want to invoke printInventory
, you just want to pass a pointer to it. That's just:
actionAdder('i', &Player::printInventory, "Print inventory");