C++ 函数指针作为函数参数
我一直在编写一个实用程序,作为GLFW键输入的包装器 我希望有一套功能,使我能够轻松地传递按键代码,并在按下或释放按键时触发该功能 我认为这里的一切都是正确的,但我试图在我的游戏类中使用它,我得到以下错误: game.cpp(27):错误C2664:“void KeyManager::press(int,void*)”:无法将参数2从“void(u thiscal::*)(void)”转换为“void*” 1> 没有可以进行此转换的上下文 Game.cpp:C++ 函数指针作为函数参数,c++,vector,map,key,glfw,C++,Vector,Map,Key,Glfw,我一直在编写一个实用程序,作为GLFW键输入的包装器 我希望有一套功能,使我能够轻松地传递按键代码,并在按下或释放按键时触发该功能 我认为这里的一切都是正确的,但我试图在我的游戏类中使用它,我得到以下错误: game.cpp(27):错误C2664:“void KeyManager::press(int,void*)”:无法将参数2从“void(u thiscal::*)(void)”转换为“void*” 1> 没有可以进行此转换的上下文 Game.cpp: void Game::testKey
void Game::testKey()
{
std::cout << "Key Up Pressed" << std::endl;
}
void Game::init()
{
// KEY MANAGER:
KeyManager::initialize();
KeyManager::press(GLFW_KEY_UP, &Game::testKey);
void Game::testKey()
{
std::cout当您获取一个非静态成员函数的地址时,您不会得到一个指向函数的“普通”指针,而是一个指向成员函数的指针:成员函数不仅将显式指定的参数作为参数,而且还获取指向对象的隐式指针(这将成为这个
)因此,Game::testKey
的类型不是void(*)(
),而是void(Game:*)()
,表明调用此函数时仍需要传入Game
对象
如果可以控制所调用函数的类型,最好使用函数对象的模板参数,或者如果需要存储这些对象的多个,最好使用带有合适类型的签名的function
,在您的情况下可能是void()
:这些对象可以存储对象,您可以传入所需的对象,例如:
std::function<void()> fun(std::bind(&Game::testKey, this));
稍后,当您有合适的游戏
对象时,可以添加一个处理函数:
KeyManager m;
Game g;
m.addHandler(std::bind(&Game::keyDown, &game));
请注意,Game::keyDown
实际上使用的是Gane
对象,没有额外的参数:这没关系,因为从std::bind()
返回的函数对象只会忽略额外的参数。当您获取非静态
成员函数的地址时,您不会返回“正常”指向函数的指针,而是指向成员函数的指针:成员函数不仅将显式指定的参数作为参数,而且还将指向对象的隐式指针(成为this
)作为参数。因此,游戏::testKey
的类型是而不是void(*)
但它相当于void(Game::*)()
,表示调用此函数时仍需要传入Game
对象
如果可以控制所调用函数的类型,最好使用函数对象的模板参数,或者如果需要存储这些对象的多个,最好使用带有合适类型的签名的function
,在您的情况下可能是void()
:这些对象可以存储对象,您可以传入所需的对象,例如:
std::function<void()> fun(std::bind(&Game::testKey, this));
稍后,当您有合适的游戏
对象时,可以添加一个处理函数:
KeyManager m;
Game g;
m.addHandler(std::bind(&Game::keyDown, &game));
请注意,Game::keyDown
实际上使用的是Gane
对象,没有额外的参数:这是从std::bind()返回的函数对象
将忽略其他参数。如果每次我想向KeyManager添加侦听器函数时都必须创建一个模板/签名,这就有点违背了这一点。是否有任何方法可以让它以我显示的方式工作KeyManager::press(GLFW\u KEY\u UP,&Game::testKey);
可能通过更改KeyManager函数来实现?@syntheypher:是的,当只使用一个函数对象时,使用模板化函数对象非常有效(因为它可以内联)。因此,您可以使用带有固定签名的函数(例如void()
),而不是。正如答案中已经写的。很抱歉,我仍然停留在这一点上,你能写一个更完整的示例,说明如何将其合并到KeyManager.cpp和Game.cpp中吗?我遇到了一个问题,它无法解析std::bind到std::function,这是addHandler参数。如果我必须创建一个模板,这就有点失败了te/signature每次我想给KeyManager添加一个侦听器函数时。是否有任何方法可以让它像我展示的那样工作KeyManager::press(GLFW_KEY_UP,&Game::testKey);
可能通过更改KeyManager函数来实现?@SyntheCypher:是的,使用模板化函数对象工作得非常好,效率也很高(因为它可以内联)当只使用一个函数对象时。因此,您将使用带有固定签名的函数(例如,void()
),而不是。正如答案中已经写的那样。很抱歉,我仍然停留在这个问题上,您能否编写一个更完整的示例,说明如何将其合并到KeyManager.cpp和Game.cpp中?我遇到一个问题,它无法解析std::bind到std::function,这是addHandler参数。