Unable to call member function pointer that is ins

2019-07-27 22:52发布

问题:

I've been racking my brain over getting the syntax right on declaring, defining and finally calling a member function pointer inside my program.

I'm writing a window manager with Xlib, and am trying to enable the user to define all key bindings in a vector of Keybinds. The Keybind struct contains more member variables, which I have left out here for the sake of brevity.

Here's what I've got so far.

Keybind, a struct containing a member variable, func, that points to a MyClass member function.

struct MyBind {
    MyBind(void (MyClass::*_func)(const XKeyEvent&))
    : func(_func) {}

    void (MyClass::*func)(const XKeyEvent&);
}

Declaration and populating of a vector that holds user-defined Keybinds.

// in my_class.hh
std::vector<MyBind*> my_binds_;

// in my_class.cc, constructor
my_binds_.push_back(new MyBind( &MyClass::do_this ));
my_binds_.push_back(new MyBind( &MyClass::do_that ));

At this point, everything compiles and runs.

Now, when I try to delegate work by iterating over the my_binds_ vector, things go wrong. It is worth noting that I've left out error handling and other member variable accesses for clarity.

void
MyClass::handle_input(const XKeyEvent& e)
{
    for (const MyBind* my_bind: my_binds_) {
        (my_bind->*func)(e); // erroneous line
    }
}

This should be the correct syntax, but it fails to compile, stating error: ‘func’ was not declared in this scope (g++, similar error from clang++).

This is weird to me, as replacing the erroneous line of code with auto test = keybind->func; does compile.

What am I doing wrong? Is there a better way to handle user key bind definitions? Thanks!

回答1:

It would be best to use std::function and forget about raw member-function pointers altogether. They will only bring you pain :)

The problem with you code is that you only have a pointer to a method but no object. Your bind struct should also store an object pointer to call the method on:

struct MyBind {
    MyBind(MyClass *obj, void (MyClass::*_func)(const XKeyEvent&))
    : obj(obj), func(_func) {}

    MyClass *obj;
    void (MyClass::*func)(const XKeyEvent&);

    void operator()(const XKeyEvent& event) const
    {
        (obj->*func)(event);
    }
}

And then use it like this:

void
MyClass::handle_input(const XKeyEvent& e)
{
    for (const MyBind* my_bind: my_binds_) {
        (*my_bind)();
    }
}

I've added a call operator to the bind struct for convenience. Note that the ->* operator is applied to the object the method belongs to.



回答2:

This is not an answer, rather a pointer to your answer or my so-question :)

You had to use

(this->*(my_bind->func))(e); 

instead of:

(my_bind->*func)(e); 

I have re-created your error msg and asked a question after many different attempts.

See this( pointer to your answer ;) ): How to call pointer to member function, which has been saved in a vector of custom struct?

MyBind holds the pointer to member function of some instance of MyClass. Therefore in order to call these function pointers, you need to explicitly tell using this keyword, for which instance of MyClass you want the func to be called.



标签: c++ c++11 x11 xlib