c++ - 接口(interface)和实现问题?

标签 c++ macros glfw

目前,在我正在开发的游戏中,我有一个窗口类:

class UserWindow{
    *interface here*
};

我已经竭尽全力避免暴露这个窗口的实现细节;具体来说,它在底层使用了 GLFW。我不想向客户端公开任何 GLFW,在我最终最终删除/替换它的情况下。一切都很好,直到我终于开始处理窗口的键输入。你看,GLFW 使用宏来识别键,如下所示:

auto GLFWKeyPressCallback(GLFWwindow* wind, int key, int, int, int) -> void {
    if(key == GLFW_KEY_???)
        *do stuff*
} 

大多数 C++ 程序员都知道,宏是有毒的,应该避免使用。这里的问题是我为用户提供了一个 UserWindowEventListener 接口(interface)来连接和接收事件。问题是,如何在不公开整个 GLFW API 本身的情况下公开这些 GLFW key 的标识符?由于 GLFW 使用前面提到的(邪恶的)宏来识别这些,它们会渗入全局命名空间,这破坏了拥有“内部”命名空间的想法。我想到的唯一其他解决方案是使用一个普通的 ol' 结构,其中包含每个键的静态整数,并将它们分配到 .cpp 文件中,如下所示:

.hpp:

struct UserWindowKey{
    static const int up, down, left, right... (repeat ad nauseam)   
};

.cpp:

const int UserWindowKey::up = GLFW_KEY_UP...

然而,这看起来很乏味、难以管理,而且通常感觉完全是一种糟糕的做法。有什么想法吗?

编辑:伪代码中的一些实现细节,以消除任何歧义:

用户窗口:

//constructor
UserWindow(){
    //key_func just fires the signal that's in the event handler below.
    glfwSetKeyCallback(window_handle, key_func);
}

用户窗口事件监听器:

struct UserWindowEventListener{
    key_signal_type key_signal;
};

用法:

auto main() -> int {
    UserWindow wind;
    wind.event_listener.key_signal.connect(*MY_FUNC*);
    wind.event_listener.poll();
}

最佳答案

我会创建一个中间方法,将 GLFW key 转换为您自己的 key ,以您熟悉且感觉理智的方式定义。就个人而言,我会使用这样的枚举:

enum MyKeys
{
    UP,
    DOWN,
    LEFT,
    RIGHT,
    // the rest
}

然后用户会为您提供回调,而您会为 GLFW 提供不同的回调。当 GLFW 调用您的回调时,您将 key 转换为您的公共(public)枚举,然后触发用户提供的回调。

回调的伪代码可能类似于:

auto GLFWKeyPressCallback(GLFWwindow* wind, int glfwKey, int a, int b, int c) -> void
{
    auto myKey = ConvertGlfwKeyToMyKey(glfwKey);
    user_callback(myKey, a, b, c);
}

user_callback 签名看起来像这样:

void user_callback(MyKeys, int, int, int);

ConvertGlfwKeyToMyKey 可能看起来像这样:

MyKeys ConvertGlfwKeyToMyKey(glfwKey)
{
    switch (glfwKey)
    {
    case GLFW_KEY_UP:
        return MyKeys.UP;
    case GLFW_KEY_DOWN:
        return MyKeys.DOWN;
    // the rest
    }
}

该系统的明显缺点是您必须通过并填写 Convert 功能。优点是您已经从用户那里抽象出所有 GLFW 内容,而无需使用任何宏或用一堆结构污染您的代码。

或者,您可以选择其他一些机制将 GLFW key 映射到 MyKeys。如果 GLFW 键覆盖了一个范围内的所有值,您可以按照相同的顺序对您的枚举进行排序,然后只需将 GLFW int 偏移并类型转换为您的枚举。

关于c++ - 接口(interface)和实现问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24567061/

相关文章:

使用 C 宏调用关联*函数

macros - 我可以用我自己的自定义宏覆盖标准库中的宏吗?

c++ - 使用 glfw3 glew 和 opengl 在 Visual Studio 社区中获取访问冲突异常

c++ - C/C++ 字符串转移到特定元素 - 最少的步骤

c++ - 独特元素的组合,无需重复

c++ - 将具有绑定(bind)成员函数的 std::bind 对象传递给函数

c++ - 在 C++ 中更新静态函数中的非静态成员

c++ - vector push_back() with reserve() 运行缓慢

lambda - 线程宏 -> 带有匿名函数

windows - Windows 上的 glfwSwapBuffers() 和垂直刷新