2016-04-28 63 views
0

我正在製作一個菜單欄,它接受菜單項。我想要包含菜單欄的窗口來決定菜單項的行爲。所以我希望窗口將一個函數傳遞給菜單項。在一個類的成員中保存一個函數指針

我最好的嘗試讓我這個錯誤:

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(); 
} 
+0

嗯,你嘗試過沒有的'SF :: RenderWindow'成員,但來自派生類的函數指針。 –

+0

啊...我直到現在纔看到您的評論。謝謝,那就是訣竅。 – MrMxyztplk

回答

0

兩個給出的答案是在我的頭上了一點。我花了一些時間看看Jan的std ::函數,並在這個過程中學到了更多。這是我做錯了:

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 
} 
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(); 

然後。

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 
} 
相關問題