void与void*参数不兼容:新手如何正确传递void函数作为参数?
解决函数指针作为参数传入的问题
你的代码里的几个核心错误
- 传递函数的方式错误:你写
glfwSetWindowShouldClose(window, GL_TRUE)的时候,是直接执行了这个函数,而不是传递它的指针。这个函数返回void,根本没法作为参数传入。 - 函数指针类型错误:用
void* fun来接收函数指针不符合C++标准,而且就算编译过,直接写fun;也不会执行函数,只是对指针求值而已。 - 逻辑判断错误:
key == keyname是把GLFW的键枚举值(比如GLFW_KEY_T)和扫描码(glfwGetKeyScancode的返回值)做比较,这两个值完全不是一回事,这个判断永远不会成立。
修正方案1:使用匹配的函数指针类型
因为你要传递的glfwSetWindowShouldClose签名是void(GLFWwindow*, int),所以先定义一个和它匹配的函数指针类型:
#include <GLFW/glfw3.h> // 定义和目标函数签名一致的函数指针类型 using WindowAction = void(*)(GLFWwindow*, int);
然后修改你的standardKeyPressRelease函数,修正逻辑并正确调用传入的函数:
static void standardKeyPressRelease(GLFWwindow* window, int targetKey, int currentKey, int action, WindowAction fun, bool triggerOnPress) { // 先判断当前触发的键是否是目标键,再判断动作是否符合要求 if (currentKey == targetKey) { if ((action == GLFW_PRESS && triggerOnPress) || (action == GLFW_RELEASE && !triggerOnPress)) { // 传入函数需要的参数,执行函数 fun(window, GL_TRUE); } } }
最后修改回调函数,正确传递函数指针:
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod) { // 传递函数名即可(函数名会隐式转为函数指针) standardKeyPressRelease(window, GLFW_KEY_T, key, action, glfwSetWindowShouldClose, true); }
修正方案2:用std::function+lambda(更灵活)
如果以后要传递不同签名的函数,用std::function结合lambda封装会更方便,不需要关心原函数的参数:
#include <GLFW/glfw3.h> #include <functional> static void standardKeyPressRelease(GLFWwindow* window, int targetKey, int currentKey, int action, const std::function<void()>& fun, bool triggerOnPress) { if (currentKey == targetKey) { if ((action == GLFW_PRESS && triggerOnPress) || (action == GLFW_RELEASE && !triggerOnPress)) { // 直接调用封装好的无参函数 fun(); } } } void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod) { // 用lambda把带参数的函数调用封装成无参的可调用对象 standardKeyPressRelease(window, GLFW_KEY_T, key, action, [window](){ glfwSetWindowShouldClose(window, GL_TRUE); }, true); }
注意事项
- 不要用
static_cast或dynamic_cast把函数指针转成void*,这不符合C++标准,而且容易导致未定义行为。 - 传递函数指针时,一定要保证函数签名和你定义的指针类型完全匹配,否则会编译错误或者运行时出错。
内容的提问来源于stack exchange,提问作者Tyrannys
相关产品推荐
相关产品推荐

