В OpenGL часто записывается такой код:
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
destructor, состояние восстанавливается, и жизнь хороша.
Тем не менее, я не совсем счастлив. Особенно, если конструктор принимает некоторые аргументы (например, флаги для glEnable
), легко забыть назначить объект переменной:
WithEnabledFlags(GL_BLEND); // whoops!
Временное уничтожается немедленно, и изменение состояния отменяется преждевременно.
Другая проблема заключается в том, что любой, кто читает мой код, может запутаться: "Почему здесь объявлена переменная, которая никогда не используется? Позвольте избавиться от нее!"
Итак, мои вопросы: Это хороший образец? Может, у него даже есть имя? Существуют ли какие-либо проблемы с этим подходом, которые я пропускаю? И последнее, но не менее важное: есть ли хорошие альтернативы?
Обновление: Да, я предполагаю, что это форма RAII. Но не так, как обычно используется RAII, потому что он включает в себя бесполезную переменную; "ресурс", о котором идет речь, никогда не обращается явно. Я просто не понимал, что это конкретное использование было настолько распространенным.