将未知类的成员函数连接到增强信号
Posted
技术标签:
【中文标题】将未知类的成员函数连接到增强信号【英文标题】:Connect member function from unknown class to boost signal 【发布时间】:2017-02-21 14:56:30 【问题描述】:我知道有很多关于这个的话题,但我就是想不通。
我正在为我的游戏使用信号驱动的输入管理器,由于我需要控制多个玩家,我需要将 PlayerController 实例的成员函数连接到我的信号向量。
问题是,不仅会有 PlayerController,还有 MenuController 等。所以我还需要将 MenuController 的成员函数连接到信号。
我很确定我已经接近解决方案,但我似乎无法弄清楚。
谁能帮我解决一下 registerEvent 函数签名以及如何调用 connect 方法。
InputManager.tcc
#include "boost/function.hpp"
template<class T>
void InputManager::registerEvent(SDL_Keycode key,KeyState state,boost::function<void ()> const& function)
auto &inputEvents = (state == KeyState::Up) ? m_keyUpEvents : m_keyDownEvents;
if(inputEvents.find(key) == inputEvents.end())
inputEvents.insert(std::make_pair(key, boost::signals2::signal<void()>()));
m_keyStates[key] = KeyState::Up;
inputEvents[key].connect(boost::bind(T::function, instance));
InputManager.hpp:
#ifndef SSB_INPUTMANAGER_HPP
#define SSB_INPUTMANAGER_HPP
#include <functional>
#include <algorithm>
#include <vector>
#include <map>
#include <SDL_keycode.h>
#include <SDL_events.h>
#include <boost/signals2.hpp>
enum KeyState
Down,
Up
;
class InputManager
public:
InputManager();
template<class T>
void registerEvent(SDL_Keycode key,KeyState state, boost::function<void ()> const& function);
void pollEvent(SDL_Event event);
private:
std::map<SDL_Keycode, boost::signals2::signal<void ()>> m_keyDownEvents;
std::map<SDL_Keycode, boost::signals2::signal<void ()>> m_keyUpEvents;
std::map<SDL_Keycode, KeyState> m_keyStates;
;
#include "InputManager.tcc"
#endif //SSB_INPUTMANAGER_HPP
PlayerController.hpp
#ifndef SSB_PLAYERCONTROLLER_HPP
#define SSB_PLAYERCONTROLLER_HPP
class PlayerController
public:
void jump();
private:
Player m_player;
;
#endif //SSB_PLAYERCONTROLLER_HPP
然后我想在我的游戏某处调用一个初始化方法:
PlayerController playerController;
InputManager inputController;
inputController.registerEvent(SDLK_0, KeyState::Down, playerController.jump());
【问题讨论】:
【参考方案1】:boost::function<>
和 std::function<>
都已经进行了类型擦除。这意味着它们“抽象”掉任何绑定参数。
this*
参数实际上只是:一个参数。所以,同样的道理。
Live On Coliru (c++11)
#include <boost/function.hpp>
#include <boost/signals2.hpp>
#include <map>
#include <iostream>
enum SDL_Keycode K_A, K_B, K_C, K_Up, K_Down, K_Right, K_Left, K_LCtrl, /*etc....*/ ;
enum KeyState Down, Up ;
struct InputManager
void registerEvent(SDL_Keycode key, KeyState state, boost::function<void()> const &function)
auto& map = state == Up? m_keyUpEvents : m_keyDownEvents;
map[key].connect(function);
void poll_event()
// hardcoded for demo
m_keyDownEvents[K_B]();
private:
std::map<SDL_Keycode, boost::signals2::signal<void()>> m_keyDownEvents;
std::map<SDL_Keycode, boost::signals2::signal<void()>> m_keyUpEvents;
std::map<SDL_Keycode, KeyState> m_keyStates;
;
struct Player ;
class PlayerController
public:
void jump()
std::cout << "Player jumped\n";
private:
Player m_player;
;
class CowController
public:
void moo()
std::cout << "Cow mooed\n";
;
int main()
InputManager inputController;
PlayerController p;
inputController.poll_event(); // nothing
inputController.registerEvent(K_B, Down, [&] p.jump(); );
inputController.poll_event(); // player jumps
CowController c;
inputController.registerEvent(K_B, Down, [&] c.moo(); );
inputController.poll_event(); // player jumps, cow moos
打印
Player jumped
Player jumped
Cow mooed
C++03
如果您没有 lambda,可以使用 Boost Bind(或 std::tr1::bind
):
inputController.registerEvent(K_B, Down, boost::bind(&PlayerController::jump, boost::ref(p)));
inputController.poll_event(); // player jumps
CowController c;
inputController.registerEvent(K_B, Down, boost::bind(&CowController::moo, boost::ref(c)));
看Live On Coliru
【讨论】:
这太棒了,为了让它工作而努力了很多!谢谢!以上是关于将未知类的成员函数连接到增强信号的主要内容,如果未能解决你的问题,请参考以下文章