我正在尝试设计一个窗口对象,该对象的工作是处理GLFW窗口的所有功能(引入,回调,输入处理...)
最重要的事情之一是渲染循环。我能想到的最幼稚的设计是让renderloop方法采用不带参数的函数指针,然后在loop方法内调用它,如下所示:
class Window
{
public:
Window();
~Window();
void WindowLoop(void (*f) (void));
protected:
GLFWwindow* window;
};
void Window::WindowLoop(void (*f) (void))
{
while(!glfwWindowShouldClose(window))
{
f();
glfwPollEvents();
}
}
但是,这有很多限制。首先,它意味着该函数不能接受任何参数。这可能是问题,也可能不是问题。
我已经做过一些研究,显然您可以传递带有任意数量参数的函数指针,但这似乎既困难又不建议。
另一个选项是通用函子,然后可以将参数定义为类/结构的一部分,而不必进行处理。
我可能还不知道其他潜在的设计。
在C ++中,哪种渲染循环设计是不错的选择,它试图优先考虑使用的多功能性和执行速度?
答案 0 :(得分:1)
我的简短答案应该是:
使用std::function
代替原始函数指针。这样可以为您提供更大的灵活性:
仍然需要为呼叫定义签名,但是您可以提供自己可能需要的回叫上下文。
这就是它的外观:
#include <functional>
class Window
{
public:
Window();
~Window();
void WindowLoop(std::function<void()> f);
protected:
GLFWwindow* window;
};
void Window::WindowLoop(std::function<void()> f)
{
while(!glfwWindowShouldClose(window))
{
f();
glfwPollEvents();
}
}
(看起来与OP的原始示例没什么不同。)
三思而后行,我发现值得一提的是小部件集及其提供的解决方案(有同样的问题要解决)。
两个通用解决方案是
virtual
用于事件处理程序的方法,可以重写。信号基本上就是带有函数指针(或std::function
或类似对象)的容器。在某些情况下会发出信号(即调用存储的函数指针)。因此,其他对象可以在那种情况下得到通知(通过在信号中注册其信号处理程序)。因此,除了没有临时提供函数指针而是将其存储在成员变量中之外,信号实际上与上述相似。
另一种方法是在某些情况下调用virtual
方法。要添加自定义行为,则分别为。必须派生基类,并且必须重写搜索中的virtual
方法。
在OP的情况下,可能看起来像这样:
class Window
{
public:
Window();
~Window();
void WindowLoop();
protected:
virtual void step();
protected:
GLFWwindow* window;
};
void Window::WindowLoop()
{
while(!glfwWindowShouldClose(window))
{
step();
glfwPollEvents();
}
}
void Window::step() { /* empty placeholder */ }
要在应用程序中使用它,必须使用Window
的派生类:
class GameWindow: public Window {
protected:
virtual void step() override;
};
void GameWindow::step()
{
// Do the game step stuff (e.g. rendering)
// where this (of type GameWindow) can provide the necessary context.
}
关于Qt,有各种情况的信号,还有virtual
方法,例如小部件中的事件处理程序。多数情况下可以选择-或-我不记得两者都可以使用。例如。可以为QPushButton::clicked()
注册一个信号处理程序,但是要自定义事件处理程序为mousePressEvent()
,必须重载Qt小部件以覆盖事件处理程序方法。 (还有事件过滤器的概念,但是恕我直言,这并不完全相同。)
gtkmm(至少在我过去使用的版本2中)提供了我可以记住的virtual
方法和信号的所有内容。因此,总是可以选择仅通过注册信号处理程序来派生gtkmm窗口小部件或更改/扩展gtkmm窗口小部件的行为。这可能会带来很少的额外性能成本,但是对于应用程序编程来说非常方便。