2016-04-28 1 views
0

私はメニュー項目を取り込むメニューバーを作っています。私は、メニュー項目の挙動を決定するためにメニューバーを保持するウィンドウが必要です。だから私は、ウィンドウがメニュー項目に関数を渡すようにします。クラスのメンバーに関数ポインタを保存する

私の最高の試みは私に、このエラーを得ている:

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

メニューバーを追加し、ウィンドウ:ここ

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

はMenuItem.hです:

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

与えられた2つの答えは、私の頭の上に少しでした。私はJanのstd :: functionを見ているうちに少し時間を過ごし、もう少しプロセスを学んだ。

MenuItemの関数はsf :: RenderWindowではなくMyWindowから来るので、私は宣言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 
} 
関連する問題