тогда в operator[] возвращать нужно не int& а int*& - а вести себя будет точно так же. Можете вообще читать с диска или с бараньей лопатки. Более того (и это кстати очень важно) перегрузить operator[] не только для int но и чего угодно другого: для строки, float и всего остального, и не один раз. Есть ограничение правда - аргумент может быть только один. Ха, смешные потуги жалкого компилятора, нас уже не остановить:

// Это класс, объединяющий пару аргументов

class pair {

public:

 int x; int y;

 pair(int _x=0, int _y=0):x(_x), y(_y)р {}

};

// Перегруженный operator[]

int& operator[](pair);

//использование.

OurArray[pair(1,2)].OurFunction();

Тормознем немного. Королева в восхищении, но… есть немного проблем.

Шаг 16 - Как сделать массив из чего угодно. Продолжение.

In spring, when woods are getting green,

I'll try and tell You what I mean.

L.Carroll. Through the looking glass.

Проблема собственно в том, что ради такой простой структуры нечего и сыр-бор разводить. Если нам нужен просто массив, можно просто взять его шаблон из STL или MFC. Клянусь, это будет замечательное решение, у Вас будет огромный набор возможностей, да к тому же реализованных компактно и эффективно (в меру); если у Вас нет отклонений в психике, и Вы не порываетесь ежедневно вставить ассемблерный код в прогу на VB, этого будет достаточно. Увы, иногда нужно больше.

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

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

Они не правы.

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

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

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

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

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

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

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

Еще по коду: Я написал для примера код, имитирующий базу данных наподобие SQL, потом засунул базу в класс такого массива и все такое… но получилось около 300 строк, и наглядность совсем пропала. Так что беру попроще - связанный список.

class CThat {int a;};

class CCursor;

class CArray;

class CNode;

class CNode {

public:

 int index;

 CThat* that;

 CNode* next;

 CNode (int _index, CThat* _that, CNode* _next): index(_index), that(_that), next(_next) {}

};

class CCursor {

public:

CArray* array;

int index;

CNode* node;

CCursor(CArray* _array, int _index):

array(_array), index(_index), node (NULL){};

CCursor(CArray* _array, CNode* _node):

array(_array), index (_node-›index), node (_node){};

CCursor& operator=(CThat* _that);

operator CThat*();

CThat* operator-›();

};

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату
×