Идиомы и стили С++ | страница 23



Ну, положим, Вам необходимо работать с геологической картой. Размер 1000х1000. Пять слоев. Если решать в лоб, то только для хранения и обработки геологических условий нужно иметь пять миллионов элементов. Совершенно ясно, всем и каждому, что создавать карту на основе простого массива абсолютно недопустимо. По видимому, объект карты должен хранить информацию только в ключевых точках, а значения между ними вычислять; при необходимости записи в карту следует проверять - есть ли такая точка во внутренней структуре, и если есть - записывать в нее, а если нет - создавать ее.

Наша карта сильно стала похожа на разреженный массив. Отличие в том, что в классическом разреженном массиве между "ключевыми" элементами хранятся нули, а у нас там лежит (как будто) значение предыдущего элемента. Процессы чтения и записи существенно различаются; в предыдущем шаге мы могли работать со ссылкой, читать и записывать ее. Сейчас операция чтения возвращает нам какую-то неопознанную… или неучтенную… шняжку новогоднюю, толку в нее писать никакого, она все равно свежевычисленная. Операция записи пишет. Вещи абсолютно разные, ничего общего. Авторитетные специалисты пишут: "никакого толку от оператора [],… возможности разделить чтение и запись нет… надо писать на BASIC… на бумажечке".

Они не правы.

Выход есть. Нужно взять новогоднюю шняжку, опознать и учесть ее. Потом перегрузить у ней операторы operator[](), operator-›() и оператор приведения типа к элементу массива. Вы узнаете ее? Да это сэр Хьюго Баскервиль собственной персоной, он же Умный Указатель, он же Курсор, он же Proxy-объект! Вот черт, кто бы знал… Далее его именуем Курсором за сходство с аналогом из баз данных.

Так теперь перед кодом давайте самое важное вычленим:

1. Массив возвращает в операторе operator[] курсор.

2. Курсор имеет перегруженный оператор присваивания operator=(), что позволяет нам грамотно обрабатывать вставки и записи в массив.

3. Курсор может неявно преобразовываться к значению элемента массива, что позволяет нам грамотно читать из массива.

4. Курсор имеет перегруженный оператор operator-›(), что позволяет нам читать и… и в общем все, что нужно; смотри предыдущие шаги.

Теперь мы имеем семантический массив. Внутри может быть что угодно, но снаружи он совершенно неотличим, вообще. Элджер справедливо замечает: "внутреннюю реализацию Вы можете сменить даже на последних стадиях разработки". Я справедливо замечаю: "и ни одна… не до…