Reputation: 103
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
Upvotes: 0
Views: 1253
Reputation: 303007
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");
Upvotes: 2