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

9.7 Ініціалізація глобальних об'єктів

Глобальні і статичні змінні компілятор розміщує в статичній пам'яті, і час життя таких змінних збігається з часом виконання програми. Статичні змінні ініціалізуються неявно (за умовчанням) до початку виконання функції main(). Ця ініціалізація називається статичною; явна ініціалізація, що задається програмістом, називається динамічною. Вбудовані типи за умовчанням ініціалізуються нулями. Для глобальних об'єктів невбудованих типів викликається конструктор за умовчанням (без аргументів). Якщо в класі його немає, виникає помилка трансляції. Конструктор ініціалізації застосовується для явної ініціалізації.

В рамках одного модуля порядок ініціалізації змінних вбудованих типів визначається порядком оголошення. Конструктори для створення і ініціалізації глобального об'єкту теж викликаються в порядку оголошень об'єктів. Деструктори викликаються перед завершенням програми в зворотному порядку.

Черговість статичної ініціалізації глобальних об'єктів, розміщених в різних одиницях трансляції, стандартом не визначена.

Змінні і функції, оголошені у файлі з атрибутом static, схильні до внутрішнього скріплення і є локальними в модулі, де визначені. Константи володіють властивістю внутрішнього скріплення за умовчанням. У різних файлах можна оголошувати глобальні константи з однаковими іменами. Щоб зробити константу, оголошену в одному файлі, видимою в іншому, потрібно використовувати слово extern.

// модуль з визначенням глобальної константи

extern const int a = 2;

// модуль з оголошенням тієї ж константи

extern const int a;

Функції, оголошені як inline, за умовчанням зв'язуються внутрішнім чином: функцію, яка визначена в одному модулі, не видно в іншому модулі. Так само, як і визначення класу, визначення inline-функції може бути включене в програму кілька разів – по одному разу на модуль.

Можна зробити inline-функцію глобальною, як і константу, використовуючи у визначенні extern:

// модуль з визначенням глобальної inline-функції

extern inline void f(void)

{ cout << a << "f()\n"; }

У іншому модулі досить вказати прототип:

// модуль з оголошенням зовнішньої inline-функції

void f(void);

До прототипу можна додати extern та inline:

extern inline void f(void);

Для локалізації імені у файлі замість атрибуту static в C++ дозволяється задавати анонімні (неіменовані) простори імен:

namespace // анонімний простір імен

{ // члени локального простору імен

}

Анонімні простори імен є локальними просторами для одиниці трансляції. Для кожного анонімного простору компілятор генерує унікальне внутрішнє ім'я, тому такі простори не "склеюються".

Завдання

Завдання отримуються з розділу 3 "Спадкування класів". Кожен клас повинен бути виконаний в окремому модулі програми.

Розділ 10. Контейнерні класи

10.1 Загальні відомості

Контейнерні класи – це класи, призначені для зберігання даних, організованих певним чином. Прикладами контейнерів можуть служити масиви, лінійні списки або стеки. Для кожного типу контейнера визначені методи для роботи з його елементами, незалежні від конкретного типу даних, які зберігаються в контейнері, тому один і той же вид контейнера можна використовувати для зберігання даних різних типів. Ця можливість реалізована за допомогою шаблонів класів, тому частина бібліотеки C++, в яку входять контейнерні класи, а також алгоритми та ітератори, про які буде розказано в наступних розділах, називають стандартною бібліотекою шаблонів (STL – Standard Template Library).

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

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

STL містить контейнери, що реалізовують основні структури даних, які використовуються при написанні програм, – вектори, двосторонні черги, списки та їх різновиди, словники і множини. Контейнери можна розділити на два типи: послідовні і асоціативні.

Послідовні контейнери забезпечують зберігання кінцевої кількості однотипних величин у вигляді безперервної послідовності. До них відносяться вектори (vector), двосторонні черги (deque) і списки (list), а також так звані адаптери, тобто варіанти контейнерів – стеки (stack), черги (queue) і черги з пріоритетами (priority_queue). Кожен вид контейнера забезпечує свій набір дій над даними. Вибір виду контейнера залежить від того, що потрібно робити з даними в програмі. Наприклад, при необхідності часто вставляти та видаляти елементи з середини послідовності слід використовувати список, а якщо включення елементів виконується головним чином в кінець або початок – двосторонню чергу.

Асоціативні контейнери забезпечують швидкий доступ до даних по ключу. Ці контейнери побудовані на основі збалансованих дерев. Існує п'ять типів асоціативних контейнерів: словники (mар), словники з дублікатами (multimap), множини (set), множини з дублікатами (multiset) та бітові множини (bitset).

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

Ітератор є аналогом вказівки на елемент. Він використовується для проглядання контейнера в прямому або зворотному напрямі. Все, що потрібне від ітератора – вміти посилатися на елемент контейнера і реалізовувати операцію переходу до його наступного елементу.

Поле

Пояснення

value_type

Тип елементу контейнера

size_type

Тип індексів, лічильників елементів тощо

iterator

Ітератор

const_iterator

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

reverse_iterator

Обернений ітератор

const_reverse_iterator

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

reference

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

const_reference

Константне посилання на елемент

key_type

Тип ключа (для асоціативних контейнерів)

key_compare

Тип критерію порівняння (для асоціативних контейнерів)

Константні ітератори використовуються тоді, коли значення відповідних елементів контейнера не змінюються. За допомогою ітераторів можна проглядати контейнери, не піклуючись про фактичні типи даних, які використовуються для доступу до елементів. Для цього в кожному контейнері визначено декілька методів, перерахованих в наступній таблиці.

Метод

Пояснення

iterator begin(),

const_iterator begin() const

Вказують па перший елемент

iterator end(),

const_iterator end() const

Вказують па елемент, наступний за останнім

Reverse_iterator rbegin(),

const_reverseiterator rbeginO const

Вказують на перший елемент в зворотній послідовності

reverseiterator rend(),

const_reverse_iterator rend() const

Вказують на елемент, наступний за останнім, в зворотній послідовності

У кожному контейнері ці типи і методи визначаються способом, залежним від їх реалізації. У всіх контейнерах визначені методи, що дозволяють отримати відомості про розмір контейнерів:

Метод

Пояснення

size()

Кількість елементів

max_size()

Максимальний розмір контейнера (порядка мільярду елементів)

Empty()

Булевська функція, яка показує, чи пустий контейнер

Інші поля і методи контейнерів ми розглянемо в міру необхідності. STL визначається в 13 заголовних файлах:

algorithm deque functional iterator list map

memory numeric queue set stack utility vector