Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 函数指针作为函数参数_C++_Vector_Map_Key_Glfw - Fatal编程技术网

C++ 函数指针作为函数参数

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

我一直在编写一个实用程序,作为GLFW键输入的包装器

我希望有一套功能,使我能够轻松地传递按键代码,并在按下或释放按键时触发该功能

我认为这里的一切都是正确的,但我试图在我的游戏类中使用它,我得到以下错误:

game.cpp(27):错误C2664:“void KeyManager::press(int,void*)”:无法将参数2从“void(u thiscal::*)(void)”转换为“void*” 1> 没有可以进行此转换的上下文

Game.cpp:

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参数。