c++ - C++ 中不带括号的方法
问题描述
所以我目前正在编写一个 C++ OpenGL 程序,而且我对这门语言还很陌生。什么是没有括号的方法?
我的代码块:
程序.cpp:
Input input;
glfwSetKeyCallback(window, input.HandleInput); //On this line input.HandleInput is the question at hand
输入.h
class Input
{
public:
void HandleInput(GLFWwindow* window, int key, int scancode, int action, int mods);
private:
};
输入.cpp
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include "Input.h"
void Input::HandleInput(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_F && action == GLFW_PRESS)
{
std::cout << key << " pressed.";
}
}
如果有人能告诉我如何正确执行 input.HandleInput 方法,我将不胜感激。
解决方案
该方法glfwSetKeyCallback
将函数指针作为其参数。函数指针是 C 和 C++ 功能中相对重要的部分,并且是实现回调的常用习惯,如本例所示。
GLFW 对传递给它的函数的作用是它具有系统事件的内部轮询功能(您可以使用 调用glfwPollEvents();
),在遇到系统事件时,会将其转换为可以使用回调解释的与系统无关的形式你提供的。
但是,GLFW 是用 C 编写的,无法处理 C++ 原生的更复杂、更高级的函数指针或仿函数,因此当我们将函数指针传递给 GLFW 时,我们需要将其简化为更简单的形式。对象的成员函数不会剪切它。这是因为这样的方法:
class Input
{
public:
void HandleInput(GLFWwindow* window, int key, int scancode, int action, int mods);
private:
};
偷偷地,根据编译器,实际上是这样的:
void Input__HandleInput(Input * ptr, GLFWwindow* window, int key, int scancode, int action, int mods);
由于此签名与 GLFW 对回调的期望不匹配,因此它不会接受它。
如果您打算使用类函数作为此函数的回调,则需要将其设为静态。
struct Input {//'class' is fine, but 'struct' reduces boilerplate
static void HandleInput(GLFWwindow* window, int key, int scancode, int action, int mods);
};
int main() {
glfwInit();
GLFWWindow* window = glfwCreateWindow(/*...*/);
glfwSetKeyCallback(window, Input::HandleInput);
}
但是,这可能会给您带来问题。毕竟,您可能专门为此回调功能编写了一个类,以提供对您需要的行为的一些封装。被迫恢复使用静态函数或全局函数会破坏此目的。
相反,您需要使用 GLFW 集成的用户指针功能。
struct InputHandler {
static void HandleKey(GLFWwindow* window, int key, int scancode, int action, int mods) {
//Perfectly legal: we fully intend to only permit the User Pointer to be of type 'InputHandler*'
InputHandler & handler = *reinterpret_cast<InputHandler*>(glfwGetWindowUserPointer(window));
handler.handleKeyImpl(window, key, scancode, action, mods);
}
void handleKeyImpl(GLFWwindow* window, int key, int scancode, int action, int mods) {
/*...*/
}
};
int main() {
glfwInit();
InputHandler input;
GLFWWindow* window = glfwCreateWindow(/*...*/);
glfwSetWindowUserPointer(window, &input);
glfwSetKeyCallback(window, Input::HandleInput);
}
推荐阅读
- bootstrap-4 - 如何解决 Bootstrap Tour 的“getTipElement() 不是函数”错误?
- c# - 当最终用户添加选择条件时如何在 Windows 窗体中更新 DataGridView
- python - django 中的追随者系统“bool 不可调用”
- docker - 从容器挂载主机文件时如何自动创建文件而不是目录
- c - OS X 上未定义的符号“_clone”
- node.js - 如何在 Firebase 的计划任务中执行 NumChildren()?
- r - 我无法正确格式化所需的输出
- php - 当我在 Symfony + VichUploaderBundle 中检索实体时如何获取图像 URL?
- flutter - 找不到名为“split-per-abi”的选项
- c# - 如何等到包含文件的目录在C#中被递归删除