glPushMatrix();
// modify the current matrix and use it
glPopMatrix();
基本上,状态被改变,然后执行一些使用新状态的操作,最后还原状态。
现在有两个问题:
- 很容易忘记还原状态。
- 如果中间的代码抛出异常,状态就永远不会被还原。
按照真正的面向对象编程风格,我编写了一些实用类来解决这些问题,如下所示:
struct WithPushedMatrix {
WithPushedMatrix() { glPushMatrix(); }
~WithPushedMatrix() { glPopMatrix(); }
};
现在我可以简单地像这样写出之前的例子:
WithPushedMatrix p;
// modify the current matrix and use it
p
的生命周期决定了恢复状态的确切时刻。如果抛出异常,p
的析构函数将被调用,状态将被恢复,一切都很好。
尽管如此,我并不完全满意。特别是如果构造函数需要一些参数(例如glEnable
的标志),很容易忘记将对象赋值给一个变量:
WithEnabledFlags(GL_BLEND); // whoops!
临时变量会立即销毁,状态更改也会被过早地撤销。
另一个问题是其他人阅读我的代码可能会感到困惑:“为什么在这里声明了一个从未被使用的变量?让我们将其去掉!”
所以,我的问题是:这是一个好的模式吗?它甚至可能有一个名字吗?这种方法存在任何我忽视的问题吗?最后但并非最不重要的:是否有任何好的替代方案?
更新:是的,我想这是 RAII 的一种形式。但它不是通常使用 RAII 的方式,因为它涉及一个看似无用的变量;所谓的“资源”从未被显式访问。我只是没有意识到这种用法如此普遍。