Навигация
Главная
Поиск
Форум
FAQ's
Ссылки
Карта сайта
Чат программистов

Статьи
-Delphi
-C/C++
-Turbo Pascal
-Assembler
-Java/JS
-PHP
-Perl
-DHTML
-Prolog
-GPSS
-Сайтостроительство
-CMS: PHP Fusion
-Инвестирование

Файлы
-Для программистов
-Компонеты для Delphi
-Исходники на Delphi
-Исходники на C/C++
-Книги по Delphi
-Книги по С/С++
-Книги по JAVA/JS
-Книги по Basic/VB/.NET
-Книги по PHP/MySQL
-Книги по Assembler
-PHP Fusion MOD'ы
-by Kest
Professional Download System
Реклама
Услуги

Автоматическое добавление статей на сайты на Wordpress, Joomla, DLE
Заказать продвижение сайта
Программа для рисования блок-схем
Инженерный калькулятор онлайн
Таблица сложения онлайн
Популярные статьи
OpenGL и Delphi... 65535
Форум на вашем ... 65535
21 ошибка прогр... 65535
HACK F.A.Q 65535
Бип из системно... 65535
Гостевая книга ... 65535
Invision Power ... 65535
Пример работы с... 65535
Содержание сайт... 65535
ТЕХНОЛОГИИ ДОСТ... 65535
Организация зап... 65535
Вызов хранимых ... 65535
Создание отчето... 65535
Имитационное мо... 65535
Программируемая... 65535
Эмулятор микроп... 65535
Подключение Mic... 65535
Создание потоко... 65535
Приложение «Про... 65535
Оператор выбора... 65535
Реклама
Сейчас на сайте
Гостей: 13
Пользователь: Iamorial33

Пользователей: 13,368
новичок: Goosprin
Новости
Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ
Delphi, Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog, 3D MAX, Компас 3D
Заказать программу для Windows Mobile, Symbian

Моделирование работы перекрёстка по регулированию движения на GPSS + Поя...
Расчет обратной матрицы на Delphi + Пояснительная записка
Меры близости на векторах в Delphi + Блок схемы

Проблема универсальности
Пока все хорошо и не видно никаких сложностей. Более того, наш стек «слишком» универсален — он может содержать элементы разного типа!
Однако не все так прекрасно, как представляется. Во-первых, на указатели расходуется дополнительная память.
Во-вторых, класс-стек понятия не имеет о реальном типе элементов в контейнере, поэтому не может выдать значение элемента, а вынужден выдавать указатель void *. Дальнейшее разыменование должна делать программа-клиент, обеспечивая еще и преобразование в нужный тип. При этом, конечно, приходится писать не самые красивые выражения.
Но гораздо более важным является то, что программа-клиент теперь обязана следить за памятью, ведь в контейнер помещается только указатель на некоторые данные. Этими данными владеет программа-клиент, и только она «знает», как с ними оперировать. И тут, как обычно это бывает при использовании указателей, может возникнуть множество проблем. Например, в стек вполне можно поместить адрес локальной переменной. Если стек имеет большее время жизни, чем эта переменная, то мы получим висячую ссылку. При использовании такого стека очень просто получить и потерянные ссылки. Если программа-клиент «забудет» освободить память, то при уничтожении стека-переменной (например, при выходе из блока) мы получим утечку памяти. Одним из решений проблем с указателями могут стать интеллектуальные указатели, которые в этой книге не рассматриваются1.
Дек (см. листинги 6.1, 6.2, 6.3) реализован для элементов типа double. Однако по сути дек тоже является универсальным контейнером, работа которого не зависит от типа элементов. К сожалению, использование указателей типа void * приведет к тем же проблемам, что и со стеком. Более того, поскольку в классе TDeque реализован деструктор, существует очень большая опасность получения утечек памяти. Поэтому применение нетипизированных указателей для универсализации дека не является самым лучшим решением.
Таким образом, мы видим, что написать универсальный контейнер, работа которого не зависит от типа элементов, не так-то просто. В С++ есть несколько вариантов решения этой проблемы. Одним из вариантов является наследование (см. главы 8 и 9), другим — шаблоны, включенные в С++ специально для решения такого рода проблем (см. главу 11).
Однако есть один очень простой, но очень полезный прием, который повышает степень универсальности динамических структур данных и позволяет повторно использовать уже разработанные классы с другим типом данных. Если еще раз взглянуть на класс TDeque (см. листинг 6.3), то ни в одном из компонентов класса мы не обнаружим спецификатор типа double. Поэтому явную зависимость класса TDeque от элементов типа double можно уменьшить, использовав оператор typedef:
Описание интеллектуальных указателей можно найти в [20, 25, 26, 28].
typedef double value_type:




После этого компоненты класса, явно зависящие от double, переписываются с типом value_type, например:
// в классе iterator
value_type& operator*() const
{ if (the_elem != 0) return the_elem->itern;
else { cout << "Null iterator!" << endl: abort(); }
}
// в классе TDeque - добавить элемент
void TDeque::push_front(const value_type &a)
{ Elem *p = new Elem(a); // образовали новый элемент
p->next = Head; p->prev = 0; // "привязали"
Head->prev = p; Head = p; // первым в деке
head = iterator(Head); // корректируем итератор
++count; // добавили элемент
}



Таким образом, изменение типа инкапсулируется в операторе typedef: если нам потребуется дек с другим типом элементов, нужно изменить единственную строку в классе, дублируя остальное определение без изменений. Это практически гарантирует нам отсутствие ошибок в новом деке.
Аналогично можно обобщить и класс ТАггау. Давайте оставим в классе только те операции, которые не учитывают специфику числового типа элементов. Тогда класс ТАггау фактически будет представлять собой определение динамического массива (листинг 6.10).

Листинг 6.10. Динамический массив
class ТАггау
{ public:
// определение типов
typedef std::size_t size_type;
typedef std::size_t index_type;
typedef double value_type;
typedef double & reference;
typedef double * iterator;
typedef double * pointer;
TArray(size_type size, value_type k=0.0);
TArray(const TArray &a);
TArray(const TArray &a, index_type begin, size_type k);
TArray(const iterator begin, const iterator end);
-TArrayO ; reference operator[](index_type index); const reference operator[](index_type index) const; TArray& operator=(const TArray &a);
TArray& assign(const TArray &a, index_type I, index_type r); TArray& assign(const iterator begin, const iterator end); size_type size()const { return size_array; }; iterator find(const value_type &a); friend ostream& operator <<(ostream& to, const TArray &a); friend istream& operator >>(istream& to, TArray &a); private:
size_type size_array; pointer data;
>:



И в этом классе нет ни одного метода, использующего числовую специфику элементов. Поэтому, заменяя объявление типов в операторах typedef, мы получаем возможность дублировать определение класса ТАггау для любого нужного нам типа элементов.

Резюме
Поскольку встроенных массивов явно не хватает для обработки групп однотипных данных, программистское сообщество предложило более общую конструкцию объединения однородных данных в группу — контейнер. Все контейнеры обладают некоторыми свойствами. Одним из важнейших характеристик контейнера является способ доступа к элементам: последовательный, прямой или ассоциативный.
Прямой и ассоциативный варианты доступа обычно реализуются посредством перегрузки операции индексирования operator!], а последовательный — реализацией класса-итератора. Такая реализация имеет еще и то преимущество, что отделяет интерфейс доступа от интерфейса контейнера. Так как итератор тесно связан с внутренней структурой контейнера, его обычно создают как вложенный класс.
Для контейнеров реализуется множество операций, однако одна из наиболее часто используемых — операция объединения контейнеров, реализуемая самыми разнообразными способами.
Динамические структуры данных, как правило, являются универсальными структурами, работа которых не зависит от типа элемента. Таковыми являются стек, очередь и дек, которые различаются только дисциплиной добавления и удаления элементов. Как правило, такие структуры реализуются с помощью связанных списков. Однако написать универсальный класс без использования механизма наследования или шаблонов достаточно сложно — как правило, приходится задействовать нетипизированные указатели, которые потенциально опасны.
Опубликовал Kest November 07 2013 14:36:58 · 0 Комментариев · 2615 Прочтений · Для печати

• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •


Комментарии
Нет комментариев.
Добавить комментарий
Имя:



smiley smiley smiley smiley smiley smiley smiley smiley smiley
Запретить смайлики в комментариях

Введите проверочный код:* =
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Поделиться ссылкой
Фолловь меня в Твиттере! • Смотрите канал о путешествияхКак приготовить мидии в тайланде?
Загрузки
Новые загрузки
iChat v.7.0 Final...
iComm v.6.1 - выв...
Visual Studio 200...
CodeGear RAD Stud...
Шаблон для новост...

Случайные загрузки
Графика в проекта...
TmxOutlookBarPro
Counter [Исходник...
Microsoft Press -...
База каталогов ( ...
Degisy Data Acces...
C++ Builder в за...
Искусство програм...
Pass [Исходник на...
Delphi 2005 Учимс...
ICQ
Tetris 2002
PCXReader. Програ...
Панель статистики...
Основы Delphi
Abc_component
Род Стивенс. Delp...
Ильдар Хабибуллин...
BSButton
GamesBase 3.0

Топ загрузок
Приложение Клие... 100774
Delphi 7 Enterp... 97833
Converter AMR<-... 20268
GPSS World Stud... 17014
Borland C++Buil... 14191
Borland Delphi ... 10291
Turbo Pascal fo... 7373
Калькулятор [Ис... 5984
Visual Studio 2... 5207
Microsoft SQL S... 3661
Случайные статьи
бронирования авиаб...
Прикладной интерфе...
Хэш-функция
Обеспечьте достато...
Возможности окруже...
Вспомогательные пр...
Я запустил все три...
Для этого вы блоки...
Площадь треугольни...
Вы не хотите опред...
Быстрая сортировка...
Работа со Jpeg-изо...
• Рабочая станция ...
Фаза управления
Настройки SERVERA
В отношении этих п...
16.0.
Турниры в казино Э...
Взаимодействия кла...
Объекты классов [C++]
Здравый смысл
Запуск и начало ра...
Форматированный вы...
Опции публикации
QueryInterface реф...
Статистика



Друзья сайта
Программы, игры


Полезно
В какую объединенную сеть входит классовая сеть? Суммирование маршрутов Занимают ли таблицы память маршрутизатора?