Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Не підтверджено.doc
Скачиваний:
0
Добавлен:
07.01.2020
Размер:
3.08 Mб
Скачать

Int mainO

{

kooClass ObjA(1, 2,3), ObjA(2, 3,4); cout« ObjA « ObjA;

cout« ObjA+lOO; // Відображає число 124, оскільки тут здійснюється // перетворення об'єкта класу у значення типу int.

cout« endl;

ObjA = ObjA + ObjA; // Додавання двох об'єктів класу kooClass // виконується без перетворення типу, cout« ObjA; // Відображає координати 3,5, 7

getchO; return 0;

}

Внаслідок виконання ця програма відображає на екрані такі результати:

1.2.3

2.3.4

124

З, 5,7

Як підтверджують результати виконання цієї програми, якщо в такому виразі цілочисельного типу, як cout « ObjA+ЮО, використовується об'єкт типу kooClass, то до цього об'єкта застосовується функція перетворення. У цьому випадку функція перетворення повертає значення 24, яке потім бере участь в операції додавання з числом 100. Але коли у перетворенні немає потреби, наприклад, під час обчислен­ня виразу ObjA = ObjA + ObjA, то функція перетворення не викликається.

Якщо функція перетворення створена, то вона викликатиметься скрізь, де по­трібне перетворення, враховуючи ситуації, коли об'єкт передається функції як ар­гумент. Наприклад, якщо об'єкт класу kooClass передати стандартній функції abs(), то також буде викликано функцію, що здійснює перетворення об'єкта типу kooC­lass у значення типу int, оскільки функція abs() повинна приймати аргумент цілочи­сельного типу.

Нео! хідноапам ятати'.аДля різних ситуацій можна створювати різні фун­кції перетворення. Наприклад, можна визначити функції, які перетворять об'єкти типу kooClass у значення типу double або long, при цьому створені функції будуть застосовуватися автоматично. Функції перетворення дають змогу інтегрувати нові типи класів, що створюються програмістом, у С++- середовище програмування.

Розділ 12. ВВЕДЕННЯ В СТАНДАРТНУ БІБЛІОТЕКУ ШАБЛОНІВ

Матеріал цього розділу містить інформацію про те, який за останні роки є найважливішим доповненням у мові програмування C++. Йдеться про стандартну бібліотеку шаблонів (Standard Template Library - STL). Саме внесення бібліотеки STL у мову програмування C++ було основною подією, яка наполегливо обгово­рювалася у період стандартизації мови C++. Бібліотека STL надає користувачу шаблонні класи і функції загального призначення, які реалізують багато популяр­них і часто використовуваних алгоритмів і структур даних. Наприклад, вона міс­тить підтримку векторів, списків, черг і стеків, а також визначає різні функції, які забезпечують до них доступ. Оскільки бібліотека STL складається з шаблонних класів, то алгоритми і структури даних можна застосовувати до даних практично будь-якого типу.

Бібліотека STL - це результат розроблення стандартного програмного забез­печення, який увібрав у себе одні з найскладніших засобів мови програмування C++. Щоб розуміти вміст бібліотеки STL і уміти ним користуватися, необхідно досконало засвоїти весь матеріал, викладений у попередніх розділах. Особливо добре потрібно орієнтуватися в шаблонах. Відверто кажучи, шаблонний синтак­сис, який використовує бібліотека STL, може спочатку налякати програмістів-по- чатківців, хоча він виглядає дещо складнішим, ніж є насправді. Незважаючи на те, що матеріал цього розділу є не набагато важчим за будь-який інший, наведений у цьому навчальному посібнику, проте не варто засмучуватися від того, якщо щось на перший погляд Вам видасться незрозумілим. Трохи терпіння під час перегляду прикладів і певної уваги у процесі їх детального аналізу приведе до того, що неза­баром Ви зрозумієте, як за незвичним синтаксисом ховається строга простота біб­ліотеки STL.

STL - достатньо велика бібліотека, і всі її засоби неможливо викласти в од­ному розділі. Повний опис бібліотеки STL зі всіма її особливостями і методами програмування займає цілу книгу. Мета представленого тут матеріалу - поз­найомити студентів з основними операціями, принципами проектування і основа­ми STL-програмування. Засвоївши матеріал цього розділу, студент зможете са­мостійно легко вивчити іншу частину бібліотеки STL.

У цьому розділі також описано ще один важливий клас C++ - клас string. Він призначений для визначення рядкового типу даних, який дає змогу обробляти си­мвольні рядки подібно до того, як обробляються дані інших типів за допомогою операторів. Клас string тісно пов'язаний з бібліотекою STL.

  1. Огляд стандартної бібліотеки шаблонів

Незважаючи на великий розмір стандартної бібліотеки шаблонів (STL) та ін­коли лякливий синтаксис, насправді її засоби достатньо легко використовувати, якщо зрозуміти, як вона побудована і з яких елементів складається. Тому, перш ніж переходити до перегляду прикладів, познайомимося з основними складовими бібліотеки STL.

Ядро стандартної бібліотеки шаблонів містить три основні елементи: кон­тейнери, алгоритми і ітератори. Вони працюють спільно один з іншим, надаючи тим самим користувачу готові розв'язки різних задач програмування.

Контейнери — це об'єкти, які містять інші об'єкти.

Існує декілька різних типів контейнерів. Наприклад, клас vector визначає ди­намічний масив, клас queue створює двосторонню чергу, а клас list забезпечує ро­боту з лінійним списком. Ці контейнери називають послідовними контейнерами і є базовими в бібліотеці STL. Окрім базових, бібліотека STL визначає асоціативні контейнери, які дають змогу ефективно знаходити потрібні значення на основі за­даних ключових значень (ключів). Наприклад, клас тар забезпечує зберігання пар "ключ-значення" і надає змогу знаходити потрібне значення за заданим унікаль­ним ключем.

Кожен контейнерний клас визначає набір функцій, які можна застосовувати для роботи з ним. Наприклад, контейнер списку містить функції, призначені для виконання вставлення, видалення і об'єднання елементів. А стек містить функції, які дають змогу поміщати значення у стек і витягувати їх із нього.

Алгоритми обробляють вміст контейнерів.

їх можливості містять засоби ініціалізації, сортування, пошуку і перетворен­ня вмісту контейнерів. Багато алгоритмів працюють із заданим діапазоном еле­ментів контейнера.

Ітератори - це об'єкти, які тією чи іншою мірою діють подібно до покажчи­ків. Вони дають змогу циклічно здійснювати запит до вмісту контейнера практич­но так само, як це робиться за допомогою покажчика під час циклічного доступу до елементів масиву. Існує п'ять типів ітераторів.

Табл. 12.1. Типи ітераторів

Ітератори

Опис

Довільного досту­пу (random access)

Зберігають і зчитують значення; дають змогу організувати довіль­ний доступ до елементів контейнера

Двонаправлені (bi­directional)

Зберігають і зчитують значення; забезпечують інкрементно-дек- рементне переміщення

Однонаправлені

(forward)

Зберігають і зчитують значення; забезпечують тільки інкрементне переміщення елементами контейнера

Вхідні (GetPut)

Зчитують, але не записують значення; забезпечують тільки інкре­ментне переміщення елементами контейнера

Вихідні (output)

Записують, але не зчитують значення; забезпечують тільки інкре­ментне переміщення елементами контейнера


У загальному випадку ітератор з більшими можливостями доступу, можна використовувати замість ітератора з меншими можливостями. Наприклад, одно- направлений ітератор може замінити вхідний ітератор.

Ітератори обробляються аналогічно до покажчиків. їх можна інкрементувати і декрементувати. До них можна застосовувати оператор перейменування адреси *. Ітератори оголошуються за допомогою типу iterator, який визначається різними контейнерами.

Бібліотека STL підтримує реверсивні ітератори, які є або двонаправленими, або ітераторами довільного доступу, даючи змогу переміщатися елементами пос­лідовності у зворотному порядку. Отже, якщо реверсивний ітератор вказує на кі­нець послідовності, то після інкрементування він вказуватиме на елемент, розта­шований перед кінцем послідовності.

Під час посилання на різні типи ітераторів у описах шаблонів у цьому нав­чальному посібнику буде використано такі терміни:

Термін

Наданий ітератор

Bilter

Двонаправлений

Forlter

Однонаправлений

1 niter

Вхідний

Outlter

Вихідний

Randlter

Довільного доступу

Бібліотека STL опирається не тільки на контейнери, алгоритми і ітератори, але і на інші стандартні компоненти. Основними з них є розподільники пам’яті, предикати і функції порівняння.

Ро' подільникапам яті керує виділенням пам'яті для контейнера.

Кожен контейнер має свій розподільник пам’яті (allocator). Розподільники керують виділенням пам'яті під елементи контейнера. Стандартний розподільник

  • це об'єкт класу allocator, але у разі потреби (у спеціалізованих додатках) можна визначати власні розподільники. Здебільшого стандартного розподільника є ціл­ком достатньо для реалізації програмних задумів.

Предикат повертає як результат значення ІСТИНА/ФАЛЬШ.

Деякі алгоритми і контейнери використовують спеціальний тип функції, так званий предикат (predicate). Існує два варіанти предикатів: унарний і бінарний. Унарний предикат приймає один аргумент, а бінарний - два. Ці функції поверта­ють значення ІСТИНА/ФАЛЬШ, але точні умови, які примусять їх повернути дій­сне або помилкове значення, визначаються програмістом. В іншій частині цього розділу, коли знадобиться унарна функція-предикат, на це буде вказано за допо­могою типу UnPred. У разі потреби використання бінарного предиката застосову­ватиметься тип BinPred. У бінарному предикаті аргументи завжди розташовані у порядку перший, другий стосовно функції, яка викликає цей предикат. Як для уна­рного, так і для бінарного предикатів аргументи повинні містити значення, тип яких збігається з типом об'єктів, які зберігає цей контейнер.

Функцігапорівняння порівнюють два елементи послідовності.

Деякі алгоритми і класи використовують спеціальний тип бінарного предика­та, який порівнює два елементи. Функції порівняння повертають значення true, як­що їх перший аргумент менший від другого. Функції порівняння ідентифікуються за допомогою типу Comp.

Крім заголовків, потрібних різним класам STL, стандартна бібліотека C++ містить заголовки <utility> і <functional>, які забезпечують підтримку STL. Наприк­лад, у заголовку <utility> визначається шаблонний клас pair, який може зберігати пару значень. Будемо використовувати клас pair нижче у цьому розділі.

Шаблони у заголовку <functional> дають змогу створювати об'єкти, які визна­чають функцію operator(), називаються об’єктами-функціями. їх у багатьох випад­ках можна використовувати замість покажчиків на функції. Існує декілька вбудо­ваних об'єктів-функцій, оголошених у заголовку <functional>. Нижче наведено де­які з них:

plus

minus

multiplies

divides

modulus

negate

equal to

not equal to

greater

greater equal

less

less_equal

logical_and

logical_or

logical_not

Можливо, найширше використовується об'єкт-функція less, який визначає, за яких умов один об'єкт менший від іншого. Об'єкти-функції можна використовува­ти замість реальних покажчиків на функції в алгоритмах бібліотеки STL, про які піде мова нижче. Використовуючи об'єкти-функції замість покажчиків на функції, бібліотека STL у деяких випадках генерує ефективніший програмний код.

Матеріал цього розділу не передбачає використання об'єктів-функцій, тому ми не застосовуватимемо їх безпосередньо. Детальний опис об'єктів-функцій мо­жна знайти в книзі Герберта Шілдта "Полный справочник по C+ + ".

  1. Поняття про контейнерні класи

Як уже зазначалося вище, контейнери є об'єктами бібліотеки STL, основне призначення яких - зберігання даних різних типів. Контейнери, які визначаються в бібліотеці STL, представлено в табл. 12.1. У ній також вказано заголовки, які не­обхідно помістити у програму під час використання кожного контейнера. Незва­жаючи на те, що клас string також є контейнером, який дає змогу зберігати і об­робляти символьні рядки, однак він у цю таблицю не внесений і розглядається нижче у цьому розділі.

Табл. 12.1. Контейнери, визначені в бібліотеці STL

Контейнер

Опис

Заголовок

l

2

3

bitset

Набір бітів

<bitset>

deque

Дек (двобічна черга, або черга з двобічним доступом)

<deque>

list

Лінійний список

<list>

map

Відображення, зберігає пари "ключ-значення", в яких ко­жен ключ пов'язаний тільки з одним значенням

<map>

multimap

Мультивідображення, зберігає пари "ключ-значення", в яких кожен ключ може бути пов'язаний з двома або більше значеннями

<map>


1

2

3

multiset

Множина, у якій кожен елемент необов'язково унікальний (мультимножина)

<set>

priority queue

Пріоритетна черга

<queue>

queue

Черга

<queue>

set

Множина, у якій кожен елемент унікальний

<set>

stack

Стек

<stack>

vector

Динамічний масив

<vector>

Оскільки імена типів у оголошеннях шаблонних класів довільні, контейнерні класи оголошують (уре<М-версії цих типів, що конкретизує імена типів. Деякі з найбільш популярних (уре<М-імен мають таке призначення:

size type

Певний цілий тип, приблизно аналогічний типу size_t

reference

Посилання на елемент

const reference

Константне (const-) посилання на елемент

iterator

Ітератор

const iterator

Константний (const-) ітератор

reverse iterator

Реверсивний ітератор

const reverse iterator

Константний реверсивний ітератор

valuejype

Тип значення, яке зберігається у контейнері (те саме, що і узагальнений тип туТуре)

allocator type

Тип розподільника (пам'яті)

key type

Тип ключа

key compare

Тип функції, яка порівнює два ключі

mapped_type

Тип значення, яке зберігається у відображенні (те саме, що і узагальнений тип туТуре)

value_compare

Тип функції, яка порівнює два значення


Оскільки в одному розділі неможливо розглянути всі контейнери, то в нас­тупних розділах ми подамо тільки три з них: vector, list і map. Якщо Ви зрозумієте, як працюють ці три контейнери, у Вас не буде проблем з використанням інших.