C++中不带括号的方法

Method without parenthises in C++

所以我目前正在编写一个 C++ OpenGL 程序,我对这门语言还很陌生。 没有括号的方法叫什么?

我的代码块:

Program.cpp:

Input input;

glfwSetKeyCallback(window, input.HandleInput); //On this line input.HandleInput is the question at hand

Input.h

class Input
{
public:
    void HandleInput(GLFWwindow* window, int key, int scancode, int action, int mods);
private:
};

Input.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 对回调的期望不匹配,因此不会接受它。

如果您打算使用 class 函数作为此函数的回调,则需要将其设为静态。

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);
}

但是,这对您来说可能是个问题。毕竟,您可能专门为此回调功能编写了一个 class 来提供对您所需行为的一些封装。被迫恢复使用静态函数或全局函数会破坏此目的。

相反,您需要使用 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);
}