@Sektr

Указатель на функцию члена класса. Как решить?

У меня есть map <std::string, void (*)()> keyEvents
Здесь мне нужно задать новый элемент мапу: метод объекта типа Script. Но компилятор ругается и говорит неверное преобразование типов.
void KeyEvent::Subscribe(Script* script)
{
    keyEvents["KeyPress"] = script->OnKeyPress;
}

Вызываю собственно статический метод и передаю его указатель на сам объект.
Script::Script()
{
    KeyEvent::Subscribe(this);
}

Вот так пытаюсь вызвать через указатель:
keyEvents["KeyPress"]();
Метод OnKeyPress класса Script выглядит вот так:
virtual void OnKeyPress() = 0;
  • Вопрос задан
  • 635 просмотров
Решения вопроса 2
Вам нужен std::bind для каррирования вашего метода. Нестатический метод обязательно принимает неявно первым параметром указатель на объект, у которого он вызывается. Тот самый this. Т.е. метод без параметров на самом деле является функцией с 1 параметром. Вот этот параметр и нужно зафиксировать, превратив метод в настоящую функцию без параметров.

#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;
}
Ответ написан
Комментировать
romy4
@romy4
Exception handler
Можно через функтор (std::function). я не помню уже точно, но видел такую реализацию. копайте в эту сторону.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
petermzg
@petermzg
Самый лучший программист
В С++ методы класса отличаются от обычных функций и статических методов класса тем, что
имеют дополнительный скрытый параметр на инстанс класса.
По этой причине вы не можете передать KeyEvent::Subscribe в тип void (*)()

Чтобы сохранить указатель на ваш метод класса надо обьявлять тип так:
void (Script::*)()
Но в этом случае вы получаете жесткую привязку к данному классу.

Если вам нужны методы разных классов, то такую задачу лучше решить через интерфейсы.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы