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

Шрифт
Интервал

стр.

>};


>class CFirst: public CBase {

>public:

> void passTo (CNoChange& _cb) { cout ‹‹ "first passed" ‹‹ endl; }

>};


>class CSecond: public CBase {

>public:

> void passTo (CNoChange& _cb) { cout ‹‹ "second passed" ‹‹ endl; }

>};


>class CNoChange {

>public:

> int a;

> // Это вариант с оператором - членом класса.

> CNoChange& operator‹‹ (CBase& _cb) { _cb.passTo(*this); return *this; }

>};


>// а это - свободная функция.

>//CNoChange& operator‹‹ (CNoChange& _nc, CBase& _cb)

>// {_cb.passTo(_nc); return _nc;};

>// проверить надо.

>int main() {

> CNoChange nc;

> CFirst fs;

> CSecond sc;

> nc‹‹fs;

> nc‹‹sc;

> return 0;

>}

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

Итераторы.

В Шагах 15 и 16 мы повозились с имитацией массива (коллекцией). Мы добились нормальной работы при чтении и записи в ячейки массива. Но работа с массивом этим не ограничивается. Вот захочется нам сделать что-то со всеми элементами массива, а он индексирован по строке.

>// Бред

>for (string cCounter= "a"; a ‹ "zzzz"; a++) array.[cCounter].doit();

Нет, это неправильно. Нужно сделать так, чтобы коллекция сама себя перебирала.

>CIndex index = array.getStart();

>while (!array.eof()) {

> index = array.getIndex ();

> array[index].doIt();

> array.getNext();

>};

Ну вот, на что-то похоже. Появился некий элемент index класса CIndex, без которого в принципе можно обойтись, если коллекция будет хранить текущее значение перебора внутри себя. Но вот беда - если вдруг коллекцию захотят перебрать разные клиенты? Ну глобальная она, существует вместе с программой, а обращаются к ней разные объекты, как себя перебрать бедной коллекции? В общем, подход тут такой же, как и в жизни: тебе надо, ты и шевелись, в смысле перебирай. Упомянутый выше index тут как нельзя кстати. Называем его Зингельшухером… (oops!) Простите - итератором, объявляем его дружественным коллекции, прописываем в него текущую позицию, пишем скромный набор функций навигации типа goFirst, goNext, isLast. В зависимости от того, где мы их пишем, итератор будет или активным - если функции навигации в нем, или пассивным - если они лежат в коллекции.

Итак, что делаем: в шаблон ampstack‹Type› из Шага 23 вписываем дружбу к классу итератора:

>friend class ampIter;

и сам шаблон класса итератора:

// Класс итератора, дружественный нашему стеку.

>template ‹class Type›

>class ampIter {

>private:

> ampstack‹Type›* m_stack;

> int iPosition;

>public:

> ampIter(ampstack‹Type›* _as = NULL) >: m_stack(_as), iPosition (0) {}

> int isLast(void) >{ return iPosition + 1 - m_stack-›iTop; }

> void moveStart(void) {iPosition = 0; }

> Type* moveNext(void) >{ return m_stack-›array[iPosition++]; }

>};

Итераторы - это тема, граничащая с безумием. Мы вовремя остановились на активном итераторе, шаблоне, не вложенном, с семантикой указателей. А ведь их можно вкладывать (т.е. объявлять класс итератора внутри класса коллекции), связывать с курсорами, перегружать их операторы, изменять семантику, вводить многопоточность, создавать внутри (!) итератора мгновенную частную копию коллекции и это только начало. По счастью, о нас уже позаботился Алексей Степанов, и подарил нам Библиотеку Стандартных Шаблонов - Standart Template Library, полную итераторов, равно коллекций и алгоритмов. Немного о них можно почитать на этом же сайте в разделе VC++-›STL у Артема Каева, а много - в MSDN.

Так же добавлю, что пользуюсь при подготовке Шагов компилятором BC3.1, а он поддерживает шаблоны не вполне так, как это делают современные компиляторы. То есть, если Вы просто скопируете код, вероятно он сразу даже не откомпилируется. Так что предупреждаю - если собираетесь пользоваться шаблонами - проверьте, что на эту тему думает компилятор (а так же насчет исключений и операторов вида xxxxxxx_cast‹›()).

Мне же итератор нужен был исключительно для следующих Шагов, а совпадения фамилий, характеров и событий прошу считать случайными.

Шаг 27 - Умные указатели. Перегрузка operator*, operator(),operator-›*.

Пробегая по верхам интересных идиом я упустил одну важную вещь. Поначалу она была не так важна, но пришло время замучать и ее. Я имею в виду то, что наши замечательно умные указатели,


стр.

Похожие книги