【问题标题】: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());

【问题讨论】:

    标签: c++ boost signals member-function-pointers


    【解决方案1】:

    boost::function&lt;&gt;std::function&lt;&gt; 都已经进行了类型擦除。这意味着它们“抽象”掉任何绑定参数。

    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

    【讨论】:

    • 这太棒了,为了让它工作而努力了很多!谢谢!
    猜你喜欢
    • 2011-11-21
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多