In short, I tried searching on how to do this, but I seem to be missing something. One constraint to my problem: Human.h cannot change. We must operate with what we've been given. I am also told to create the array of pointers to members to decide on which function needs to be called.
Here's what I have:
Human.h
class Human
{
private:
void meleeAttack(std::string const& target);
void rangedAttack(std::string const& target);
void intimidatingShout(std::string const& target);
public:
void action(std::string const& action_name, std::string const& target);
};
Human.cpp
#include "Human.h"
typedef void (Human::* Human_mem_fnPtr)(std::string target);
void Human::meleeAttack(std::string const& target)
{
std::cout << "Melee Attack performed on " << target << "!\n";
}
void Human::rangedAttack(std::string const& target)
{
std::cout << "Ranged Attack performed on " << target << "!\n";
}
void Human::intimidatingShout(std::string const& target)
{
std::cout << "Shout performed on " << target << "!\n";
}
void Human::action(std::string const& action_name, std::string const& target)
{
//error on initialization--expression must be an lvalue or function designation--but they ARE func designations...
Human_mem_fnPtr fnPtr[] = {&Human::meleeAttack(target), &Human::rangedAttack(target), &Human::intimidatingShout(target)};
}
From what I found online, I am going in the right direction here. What am I missing?
CodePudding user response:
A couple of points:
- Doing pointers to functions is made much easier with the
std::function<>
template class. - Using a old-style array is not really the best choice these days.
A map
or unordered_map
would be a much better option, with a definition like this:
using ActionMap = std::unordered_map<const std::string, std::function<void(const std::string&)>;
When adding your functions to this map you would use something like the following:
mActionMap["rangedAttack"] = std::mem_fn(&Human::rangedAttack);
This will give you a cleaner and easier to maintain option and should compile cleanly.
Note that the std::mem_fn
is required to wrap a member function of a class.
Edit: Per your comment below, Id still suggest using as many of the modern C constructs as possible.
using ActionFunc = std::function<void(const std::string&)>;
And then:
ActionFunc actions[] = { std::mem_fn(&Human::rangedAttack), ...}
or:
std::array<ActionFunc> actions = ...