Reputation: 135
I am creating a console menu in C++ and I want to give every item in my menu a callback function, so when an item is selected, a different function is called. So far, I have this code:
#include <iostream>
#include <vector>
using namespace std;
class Core
{
public:
void action1() {}
void action2() {}
//...
};
typedef void (Core::*CoreFunc)();
class Menu
{
struct Option
{
Option(CoreFunc cb) : callback(cb) {}
//some data
CoreFunc callback;
//some more data
};
vector<Option> m_options;
public:
Menu(Core const& core)
{
addOption(core.action1);
}
void addOption(CoreFunc callback)
{
m_options.push_back(Option(callback));
}
void execOptionX(int index)
{
m_options[index].callback();
}
};
int main()
{
Core core;
Menu menu(core);
menu.execOptionX(0);
return 0;
}
Which is giving me this error:
no matching function for call to ‘Menu::addOption(<unresolved overloaded function type>)’
at addOption(core.action1);
and also
must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘((Menu*)this)->Menu::m_options.std::vector<_Tp, _Alloc>::operator[]<Menu::Option, std::allocator<Menu::Option> >(((std::vector<Menu::Option>::size_type)index)).Menu::Option::callback (...)’, e.g. ‘(... ->* ((Menu*)this)->Menu::m_options.std::vector<_Tp, _Alloc>::operator[]<Menu::Option, std::allocator<Menu::Option> >(((std::vector<Menu::Option>::size_type)index)).Menu::Option::callback) (...)’
when I try to call the function.
I have seen many implementation of member function pointer, but they are all used within the same class.
Why am I getting these errors?
What is the correct syntax to get this code to compile/work?
Thank you
Upvotes: 1
Views: 351
Reputation: 596256
You declared CoreFunc
as a non-static pointer-to-member-method. So you need to specify a pointer to the desired method, eg:
addOption(&Core::action1);
More importantly, you also need to provide a Core
object instance as the this
parameter for the callback. You specify the object via the .*
operator (if using an object reference) or the ->*
operator (if using an object pointer), eg:
void execOptionX(int index)
{
CoreFunc callback = m_options[index].callback;
(SomeCoreObj.*callback)();
}
void execOptionX(int index)
{
CoreFunc callback = m_options[index].callback;
(SomeCoreObjPtr->*callback)();
}
So, you need to change your Menu
class to keep track of the Core
object that will be passed to the callback (assuming you don't want to pass the Core
object as a parameter to execOptionX()
, eg:
class Menu
{
struct Option
{
Option(CoreFunc cb) : callback(cb) {}
//some data
CoreFunc callback;
//some more data
};
Core &m_core;
vector<Option> m_options;
public:
Menu(Core &core)
: m_core(core)
{
addOption(&Core::action1);
}
void addOption(CoreFunc callback)
{
m_options.push_back(Option(callback));
}
void execOptionX(int index)
{
CoreFunc callback = m_options[index].callback;
(m_core.*callback)();
}
};
And of course, the Core
object has to remain alive for the lifetime of the Menu
(which it does in your main()
example).
Upvotes: 2