C ++:如何从任何类传递函数作为参数

时间:2016-07-13 14:30:31

标签: c++ function user-interface pointers std-function

我昨晚开始为我的游戏实现我的GUI系统,我决定尝试使用函数指针来处理gui事件。我之前没有使用它们,但是能够获得基本的实现。但是,我想扩展GUI系统的可用性和“通用性”。目前,我在protected超类中的protected修饰符下有一个函数指针。我在类中也有一个getter(回调)和一个setter(subscribeEvent)来为gui分配一个事件。它目前看起来像这样:

class GUI
{
public:
    …….
    ……
    std::function<void()> callback() const { return eventCallback; }
    void subscribeEvent(const std::function<void()>& callback)
    { 
        eventCallback = callback; 
    }

protected:
    std::function<void()> eventCallback;
};

要设置函数回调,可以将void函数传递给subscribeEvent,它可以正常工作。但是,您不能对任何函数使用范围分辨率修饰符,传入的函数必须是这样的全局函数。

(MainGame.h):

void global();

class MainGame
{
public:
    void Init();
    void nonGlobal();

private:
    std::vector<GUI*> _guis;
};

(MainGame.cpp):

void MainGame::Init()
{
    Button* button  = new Button(……); //< Button is a subclass of GUI
    button->subscribeEvent(global); //< This works fine
    button->subscribeEvent(MainGame::nonGlobal); //< This does not work saying something like “void(MainGame) is not of type void()”
    _guis.pushBack(button);
}

void MainGame::nonGlobal()
{
……
}

void global()
{
……
}

有没有人知道如何修改参数以允许传入任何类范围内的任何函数。这将是有帮助的,因为我可以有一个按钮事件来自玩家,敌人,项目等类而不是让每个处理函数都是全局的。我已经看到高级gui系统传递了诸如'event(handlerFunction,classtype)'之类的事件,因此你可以传递处理函数,然后传递处理函数所在的对象。这是我想采取的一种方法。

2 个答案:

答案 0 :(得分:1)

如果您使函数MainGame::nonGlobal静态:

,您的代码将会起作用
class MainGame
{
public:
    void Init();
    static void nonGlobal();

private:
    std::vector<GUI*> _guis;
};

您无法传递非静态成员函数的原因是因为成员函数具有隐式的第一个参数(this),在您的类型为MainGame*的情况下。因此,您当前尝试传递的功能实际上具有签名void(MainGame*)而不是void()

或者,您可以使用lambda绑定this参数,而不是直接传递函数:

button->subscribeEvent([this](){nonGlobal();});

答案 1 :(得分:0)

改变这个:

button->subscribeEvent(MainGame::nonGlobal); //< This does not work saying something like “void(MainGame) is not of type void()”

button->subscribeEvent(std::bind(&MainGame::nonGlobal, this)); 

通过此更改,您会遇到this的终身管理问题。