In principle there is nothing wrong with pointers to members.
See, e.g., the following code:
#include <iostream>
/** Some API */
struct Button {
virtual void OnClick() = 0;
};
struct BaseMenu {
void f1(Button* b) {
std::cout << "f1(Button*)\n";
b->OnClick();
}
void f2(Button* b) {
std::cout << "f2(Button*)\n";
b->OnClick();
}
void Update() {
}
};
typedef void(BaseMenu::*ClickAreaCallback)(Button*);
struct Message{
ClickAreaCallback func;
Button* clickArea;
BaseMenu* funObj;
};
/** Usage */
class OKButton : public Button {
void OnClick() {
std::cout << "OKButton::OnClick()\n";
}
};
int main(int nArg, char* args[]) {
// Fill message:
BaseMenu menu;
OKButton ok;
Message m1, m2;
m1.func = &BaseMenu::f1;
m1.funObj = &menu;
m1.clickArea = dynamic_cast<Button*>(&ok);
m2.func = &BaseMenu::f2;
m2.funObj = &menu;
m2.clickArea = dynamic_cast<Button*>(&ok);
(m1.funObj ->* m1.func)(m1.clickArea);
(m2.funObj ->* m2.func)(m2.clickArea);
}
But it looks like a conceptional error. You should not need the callback. The buttons should be derived from a base class and have virtual member functions that do the specific stuff.
There follows an example demonstrating the usage of inheritance instead of callbacks.
Note, that ButtonToggle is an example for storing the information inside the button and ButtonNotify is an example for the button notifying the menu.
#include <iostream>
#include <vector>
/** Some API */
struct Button {
double _area[4]; // rectangle x1,y1,x2,y2
Button(std::initializer_list<double> area) {
std::copy(area.begin(),area.begin()+4,_area);
}
virtual void OnClick() = 0;
};
class BaseMenu {
protected:
std::vector<Button*> _buttons;
public:
void Register(Button* btn) {
_buttons.push_back(btn);
}
void OnClick(double pt[2]) {
for(auto iBtn = _buttons.begin(); iBtn!=_buttons.end(); iBtn++) {
if( (*iBtn)->_area[0] <= pt[0] && pt[0] <= (*iBtn)->_area[2]
&& (*iBtn)->_area[1] <= pt[1] && pt[1] <= (*iBtn)->_area[3] ) {
(*iBtn)->OnClick();
}
}
}
};
struct MyMenu : public BaseMenu {
struct ButtonToggle: public Button {
bool _val;
ButtonToggle() :
Button( {0.0,0.0,1.0,1.0} )
{
_val = false;
}
void OnClick()
{
std::cout << "ButtonToggle::OnClick()\n";
_val = not(_val);
}
} buttonToggle;
void DoSomething() {
std::cout << "DoSomething()\n";
}
struct ButtonNotify: public Button {
MyMenu& _myMenu;
ButtonNotify(MyMenu& myMenu) :
Button( {2.0,0.0,3.0,1.0} ),
_myMenu(myMenu)
{}
void OnClick() {
_myMenu.DoSomething();
}
} buttonNotify;
MyMenu() :
buttonNotify(*this)
{
Register(&buttonToggle);
Register(&buttonNotify);
}
};
int main(int nArg, char* args[]) {
MyMenu menu;
double pt[2];
while(( std::cout << "\nCoordinates (end: -1 -1):",
std::cin >> pt[0] >> pt[1],
not( pt[0] == -1.0 and pt[1] == -1.0 ) )) {
menu.OnClick(pt);
}
}
/*
Local Variables:
compile-command: "g++ -g -std=c++11 test1.cc"
End:
*/