将函数指针保存在 class 的成员中
Saving a function pointer in member of a class
我正在制作一个包含菜单项的菜单栏。我想要包含菜单栏的 window 来决定菜单项的行为。所以我希望 window 将一个函数传递给菜单项。
我最好的尝试是得到这个错误:
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)();
}
添加菜单栏的window:
class MyWindow : public sf::RenderWindow
{
//...
void close();
};
和 window 的 cpp 文件:
MyWindow::MyWindow() : sf::RenderWindow(...)
{
//...
MenuItem item(this);
item.setBehaviour(&MyWindow::close); // error!
//...
}
//...
void MyWindow::close()
{
this->close();
}
您可以尝试解决的问题是使 MenuItem
成为模板 class:
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();
然后。
你可以使用 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
}
给出的两个答案让我有点头疼。我花了一些时间查看 Jan 的 std::function 并在此过程中学到了更多东西。这是我做错的地方:
MenuItem 的功能将来自 MyWindow,而不是 sf::RenderWindow,因此我需要转发声明 MyWindow 并将所有 sf::RenderWindow 更改为 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
}
我正在制作一个包含菜单项的菜单栏。我想要包含菜单栏的 window 来决定菜单项的行为。所以我希望 window 将一个函数传递给菜单项。
我最好的尝试是得到这个错误:
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)();
}
添加菜单栏的window:
class MyWindow : public sf::RenderWindow
{
//...
void close();
};
和 window 的 cpp 文件:
MyWindow::MyWindow() : sf::RenderWindow(...)
{
//...
MenuItem item(this);
item.setBehaviour(&MyWindow::close); // error!
//...
}
//...
void MyWindow::close()
{
this->close();
}
您可以尝试解决的问题是使 MenuItem
成为模板 class:
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();
然后。
你可以使用 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
}
给出的两个答案让我有点头疼。我花了一些时间查看 Jan 的 std::function 并在此过程中学到了更多东西。这是我做错的地方:
MenuItem 的功能将来自 MyWindow,而不是 sf::RenderWindow,因此我需要转发声明 MyWindow 并将所有 sf::RenderWindow 更改为 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
}