我正在创建一个菜单栏,其中包含菜单项。我希望包含菜单栏的窗口决定菜单项的行为。所以我希望窗口将一个函数传递给菜单项。
我最好的尝试是给我这个错误:
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 :(得分: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
}