S
S
Sektr2016-01-07 23:25:59
C++ / C#
Sektr, 2016-01-07 23:25:59

A pointer to a class member function. How to decide?

I have map <std::string, void (*)()> keyEvents
Here I need to set a new element to the map: a method of an object of type Script. But the compiler swears and says incorrect type conversion.

void KeyEvent::Subscribe(Script* script)
{
    keyEvents["KeyPress"] = script->OnKeyPress;
}

I call the actual static method and pass its pointer to the object itself.
Script::Script()
{
    KeyEvent::Subscribe(this);
}

This is how I try to call through a pointer:
keyEvents["KeyPress"]();
The OnKeyPress method of the Script class looks like this:
virtual void OnKeyPress() = 0;

Answer the question

In order to leave comments, you need to log in

2 answer(s)
M
Maxim Moseychuk, 2016-01-08
@Sektr

You need it std::bindto curry your method. A non-static method must implicitly take as its first parameter a pointer to the object on which it is called. The same this. Those. a method with no parameters is actually a function with 1 parameter. It is this parameter that needs to be fixed, turning the method into a real function without parameters.

#include <functional>
#include <iostream>
#include <string>
#include <map>

class Foo {
public:
  Foo(std::string msg): m_msg(msg) {}
  void event() {
    std::cout << m_msg << std::endl;
  }
private:
  std::string m_msg;
};

int main() {
  auto foo = new Foo("Foo");
  auto bar = new Foo("Bar");

  std::map<std::string, std::function<void ()>> keyEvents = {
    {"foo", std::bind(&Foo::event, foo)},
    {"bar", std::bind(&Foo::event, bar)}
  };

  for(auto callback: keyEvents) {
    std::cout << callback.first << ":";
    callback.second();
  }

  keyEvents.clear();
  delete foo;
  delete bar;
  return 0;
}

P
Peter, 2016-01-07
@petermzg

In C++, class methods differ from regular functions and static class methods in that they
have an additional hidden parameter per class instance.
For this reason, you cannot pass KeyEvent::Subscribe to void (*)() type.
To store a pointer to your class method, you must declare the type like this:
But in this case, you get a hard binding to this class.
If you need methods of different classes, then it is better to solve such a problem through interfaces.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question