
- •8.2.1. Реалізація класів
- •8.2.2. Породження об’єктів
- •8.2.3. Виклик операцій
- •8.2.4. Використання успадкування
- •8.2.5. Реалізація залежностей
- •8.2.6. Шаблони, шаблони-класи
- •Параметри шаблонів, що опускаються
- •Приклади, які використовують вектори символів
- •8.2.8. Основні компоненти stl
- •8.2.8.1. Контейнери
- •Контейнери послідовностей
- •Впорядковані асоціативні контейнери
- •8.2.8.2. Параметричні (родові) алгоритми
- •8.2.8.3. Ітератори
- •8.2.8.4. Об’єкти-функції
- •8.2.8.5. Адаптери
- •8.2.8.6. Алокатори
- •8.2.9. Stl та об’єктно-орієнтоване програмування
Параметри шаблонів, що опускаються
Ще однією порівняно новою властивістю шаблонів у мові С++ є можливість опускати параметри шаблонів. Наприклад, визначення шаблона-класу vector y STL має вигляд:
template <class T, class Allocator = allocator >
class vector {
...
};
Для другого параметра цього шаблона (Allocator) визначено значення allocator цього параметра, якщо відповідний йому фактичний параметр шаблона опущений. Усі вміщуючі класи (контейнери) STL використовують засоби управління пам’яттю, які забезпечуються відповідним класом Allocator, а allocator — це тип (визначуваний як клас), котрий забезпечує стандартні засоби управління пам’яттю. Оскільки Allocator має значення, яке опускається, немає потреби щоразу визначати цей параметр при породженні примірника (об’єкта) класу vector, тобто vector < int > еквівалентне vector < int, allocator >.
8.2.7. Параметричне програмування мовою С++ з використанням стандартної бібліотеки шаблонів STL
Стандартна бібліотека шаблонів STL (Standard Template Library) забезпечує можливість параметричного програмування мовою С++. Вона включає в останню попередню версію (Draft) стандарту мови С++. Тут міститься короткий огляд бібліотеки та приклади використання її компонентів.
Файли — заголовки STL.
Для того щоб скористатися компонентами STL у своїй програмі, необхідно застосувати директиву препроцесора #include для включення одного чи кількох файлів-заголовків. В усіх прикладах припускається, що структура й іменування файлів-заголовків STL задовольняють такі погодження:
Вміщуючий клас (контейнер) STL з ім’ям с міститься у файлі < c.h >; наприклад, vector у файлі < vector.h >, list у файлі < list.h > і т. д.
Адаптери вміщуючих класів(контейнерів) STL(stack, queue та priority_queue) містяться у файлі <stack.h>.
Усі параметричні алгоритми STL містяться у файлі <algo.h>.
Ітераторні класи та адаптори ітераторів STL містяться у файлі <iterator.h>.
Об’єкти функції та адаптори функції STL містяться у файлі <function.h>.
Усі основні деталі та більша частина менш важливих деталей ілюструється прикладами, які розроблені в такий спосіб, щоб їх можна було читати й розуміти візуально, не виконуючи на комп’ютері. Однак більшість прикладів допускає компіляцію та виконання з різними установками фактичних параметрів, дозволяє повільніше демонструвати можливості STL. Щоб приклади були зрозуміліші, у них широко застосовується стандартний макрос С/C++assert (див. файл-заголовок assert.h). Цей макрос розглядає вираз із бульовим значенням, переданим йому як аргумент, та нічого не робить, якщо значення вказаного виразу є true. Якщо ж це значення дорівнює false, то макрос друку друкує повідомлення та завершує програму. Спочатку розглянемо приклад, в якому взагалі не використовується STL.
Приклад 8.1. Застосування макрос assert.
#include <iostream.h>
#include <assert.h>
#include <string.h>
int main ()
{
cout<<«Illustrating the Assert macro.»<< end1;
char* string0 = mark twain;
char string1[20];
char string2[20];
strcpy(string1, string0);
strcpy(string2, string0);
int N1 = strlen(string1);
int N2 = strlen(string2);
assert (N1==N2);
//put the reverge of string1 in string2:
for(int k=0; k!=N1; ++k)
string2[k]= string1[N1-1-k];
assert(strcmp(string2, «niawt kram») == 0);
};
У цьому прикладі при першому використанні assert перевіряється, що довжини сторін string1 та string2 однакові. Друге використання assert перевіряє, що рядок string2 містить послідовність символів «niawt kram».
Якщо у програмі є помилка — або в обчисленнях, або в операторах assert, — виконання програми припиняється і друкується відповідне повідомлення. Наприклад, у програмі помилково було надруковано:
for (int k=0; k!=N1; ++k)
string2[k]= string1[N1-k];
(помилка в індексі масиву: замість правильного string1 [N1-1-k] надруковано string1 [N1-k], у цьому разі виконання програми приведе до такого друку:
Illustrating the аssert macro.
Assertion failed: assert(strcmp(string2, «niawt kram») == 0),
file: c:\st1\examples\ex01-01a.cpp, line 24
Такий самий текст буде і в разі помилки в assert, наприклад, якщо у програмі буде написано:
for(int k=0; k!=N1; ++k)
string2[k]= string1[N1-1-k];
assert(strcmp(string2, «naiwt kram») == 0);
(помилка полягає в тому, що замість правильного «niawt» написано «naiwt». Звичайно, можливі й інші помилки, які можуть бути виявлені за допомогою assert.
Приклад використання макросу assert разом із STL
STL дозволяє параметризувати програму, оскільки STL містить параметричний алгоритм reverse, який дає змогу діставати дзеркальне відображення багатьох видів послідовностей, у тому числі — рядків символів. Розглянемо приклад:
#include < iostream.h >
#include < algo.h > // містить алгоритм reverse
#include < assert.h >
#include < string.h >
int main ()
{
cout<<«Using reverse algorithm with an array.«<< end1;
char* string1 = «mark twain»;
int N1 = strlen(string1);
reverse(string1, string1+N1);
assert(strcmp(string1, «niawt kram») == 0);
};
Параметрами reverse є покажчики початку та кінця рядка (кінцем рядка є перша позиція після останнього символа рядка). Функція забезпечує відображення рядка в самій собі.