09.04.2016 Views

Priemioop

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Паттерны поведения<br />

исключения память, занимаемая объектом-итератором, вообще никогда не<br />

будет освобождена.<br />

Эту ситуацию помогает исправить паттерн заместитель. Вместо настоящего<br />

итератора мы используем его заместителя, память для которого выделена<br />

в стеке. Заместитель уничтожает итератор в своем деструкторе. Поэтому,<br />

как только заместитель выходит из области действия, вместе с ним<br />

уничтожается и настоящий итератор. Заместитель гарантирует выполнение<br />

надлежащей очистки даже при возникновении исключений. Это пример<br />

применения хорошо известной в C++ техники, которая называется «выделение<br />

ресурса - это инициализация» [ES90]. В разделе «Пример кода»<br />

она проиллюстрирована подробнее;<br />

а итераторы могут иметь привилегированный доступ. Итератор можно<br />

рассматривать как расширение создавший его агрегат. Итератор и агрегат<br />

тесно связаны. В C++ такое отношение можно выразить, сделав итератор другом<br />

своего агрегата. Тогда не нужно определять в агрегате операции, единственная<br />

цель которых - позволить итераторам эффективно выполнить обход.<br />

Однако наличие такого привилегированного доступа может затруднить определение<br />

новых способов обхода, так как потребуется изменить интерфейс агрегата,<br />

добавив в него нового друга. Для того чтобы решить эту проблему,<br />

класс Iterator может включать защищенные операции для доступа к важным,<br />

но не являющимся открытыми членам агрегата. Подклассы класса<br />

Iterator (и только его подклассы) могут воспользоваться этими защищенными<br />

операциями для получения привилегированного доступа к агрегату;<br />

а итераторы для составных объектов. Реализовать внешние агрегаты для рекурсивно<br />

агрегированных структур (таких, например, которые возникают<br />

в результате применения паттерна компоновщик) может оказаться затруднительно,<br />

поскольку описание положения в структуре иногда охватывает<br />

несколько уровней вложенности. Поэтому, чтобы отследить позицию текущего<br />

объекта, внешний итератор должен хранить путь через составной объект<br />

Composite. Иногда проще воспользоваться внутренним итератором.<br />

Он может запомнить текущую позицию, рекурсивно вызывая себя самого,<br />

так что путь будет неявно храниться в стеке вызовов.<br />

Если узлы составного объекта Composite имеют интерфейс для перемещения<br />

от узла к его братьям, родителям и потомкам, то лучшее решение дает<br />

итератор курсорного типа. Курсору нужно следить только за текущим узлом,<br />

а для обхода составного объекта он может положиться на интерфейс<br />

этого узла.<br />

Составные объекты часто нужно обходить несколькими способами. Самые<br />

распространенные - это обход в прямом, обратном и внутреннем порядке,<br />

а также обход в ширину. Каждый вид обхода можно поддержать отдельным<br />

итератором;<br />

а пустые итераторы. Пустой итератор Nulllterator - это вырожденный<br />

итератор, полезный при обработке граничных условий. По определению,<br />

Nulllterator всегда считает, что обход завершен, то есть его операция<br />

IsDone неизменно возвращает истину.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!