将函数指针保存在类的成员中

时间:2016-04-28 15:29:52

标签: c++ function-pointers

我正在创建一个菜单栏,其中包含菜单项。我希望包含菜单栏的窗口决定菜单项的行为。所以我希望窗口将一个函数传递给菜单项。

我最好的尝试是给我这个错误:

error: no matching function for call to 'MenuItem::setBehaviour(void (MyWindow::*)())'

这是MenuItem.h:

class MenuItem{
public:
    typedef void (sf::RenderWindow::*function_type)();

    MenuItem(sf::RenderWindow* win); // window that holds the menu bar

    void setBehaviour(function_type f); // I want to be able to change the behaviour
                                        // to reuse the menu item
    void action(); // use the function

private:
    sf::RenderWindow* m_window;
    function_type     m_function;
};

MenuItem.cpp

MenuItem::MenuItem(sf::RenderWindow* win) : m_window(win)
{
    //ctor
}

void MenuItem::setBehaviour(function_type f)
{
     m_function = f;
}

void MenuItem::action()
{
    (m_window->*m_function)();
}

添加菜单栏的窗口:

class MyWindow : public sf::RenderWindow
{
    //...
    void close();
};

窗口的cpp文件:

MyWindow::MyWindow() : sf::RenderWindow(...)
{
    //...
    MenuItem item(this);
    item.setBehaviour(&MyWindow::close); // error!
    //...
}

//...

void MyWindow::close()
{
    this->close();
}

3 个答案:

答案 0 :(得分:0)

您可以尝试解决的问题是使MenuItem成为模板化的类:

template<typename RenderWindow>
class MenuItem{
public:
    typedef void (RenderWindow::*function_type)();

    MenuItem::MenuItem(RenderWindow* win) 
    : m_window(win) {
        std::static_assert(
            std::is_base_of<sf::RenderWindow,RenderWindow>()
                           ,"RenderWindow must be derived from sf::RenderWindow.");
    }

    void setBehaviour(function_type f) {
        m_function = f;
    }

    void action() {
        m_window->*m_function)();
    }

private:
    RenderWindow*     m_window;
    function_type     m_function;
};

完全省略MenuItem.cpp文件。

您可以实例化并访问MenuItem之类的

MyWindow myWindow;
MenuItem<MyWindow> closeWindow(myWindow);
menuItem.setBehavior(MyWindow::close);

// ...
menuItem.action();

然后

答案 1 :(得分:0)

您可以使用std::function

// MenuItem.h
#include <functional>

class MenuItem
{
    public:
        using function_type = std::function<void()>;
        auto setBehaviour(function_type f) -> void;
        auto action() -> void;

    private:
        function_type m_function;
};

// MenuItem.cpp
auto MenuItem::setBehaviour(function_type f) -> void
{
    m_function = f;
}

auto MenuItem::action() -> void
{
    m_function();
}

// MyWindow.cpp
#include <functional>

MyWindow::MyWindow() : sf::RenderWindow(...)
{
    MenuItem item(this);
    item.setBehaviour(std::bind(&MyWindow::close, this));
}

auto MyWindow::close() -> void
{
    // do something
}

答案 2 :(得分:0)

给出的两个答案在我的头上有点过了。我花了一些时间看着Jan的std :: function并在此过程中学到了更多。这就是我做错了:

MenuItem的函数将来自MyWindow,而不是sf :: RenderWindow,因此我需要转发声明MyWindow并将所有sf :: RenderWindows更改为MyWindow。

class MyWindow; // fix: forward declaration
class MenuItem{
    public:

    typedef void (MyWindow::*function_type)(); // fix

    MenuItem(MyWindow* win); // fix

    void setBehaviour(function_type f);

    void action();

private:
    MyWindow* m_window; // fix
    function_type     m_function;
};

MenuItem.cpp

MenuItem::MenuItem(MyWindow* win) : m_window(win) // fix
{
    //ctor
}