Namespace vector

{ // реалізація методів класу vector

vector operator+(const vector &vl, const vector &v2)

{/*...*/}

double scalar_product (const vector&v1,const vector &v2)

{/*...*/}

 

double length(const vector &v)

{/*...*/}

}

/* user.cpp. клієнтський код */

#include "vector.h"

// ...

void F(vector::vector &v)

{ // ...

double d = vector::length(v);

//...

}

 

Така організація простору імен аналогічна розділенню класу на інтерфейс та реалізацію.

9.6 Міжмодульні змінні та функції

Кожне ім'я, що позначає об'єкт, має деяку зону видимості (дії), в якій це ім'я оголошене і може використовуватися. У стандарті C++ визначені наступні зони видимості: оператор, прототип, блок, функція, клас, файл, простір імен. Імена в одній зоні видимості не мають бути однакові, але в різних областях вони можуть і збігатися. Імена, оголошені поза всіма зонами видимості, входять в глобальний простір імен. Так, всі імена Windows API входять в глобальний простір імен. Для звернення до глобального імені використовується операція дозволу контексту ::, оскільки за умовчанням (без вказівки кваліфікаторів) завжди вибирається ім'я з "найменшою" зоною видимості.

Відповідно до правила одного визначення (one-definition rule – ODR), одиниця трансляції не повинна містити більш за одне визначення будь-якої змінної, функції, класу, перерахування і шаблону. Оголошень може бути декілька: оголошення додають деяке ім'я в дану зону видимості і використовуються для узгодження типів. Змінна, визначена у файлі поза всіма класами і функціями, називається глобальною. У іншому модулі-файлі вона має бути оголошена з ключовим словом extern.

 

// Модуль з визначенням змінної

int Global = 1;

// Модуль з оголошенням змінної

extern int Global;

 

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

 

// файл з оголошенням функції

void f(void)

{ cout << "f()" << endl; }

// будь-який інший файл з прототипом функції

void f(void);

 

Слово extern писати не потрібно, хоча і не забороняється. Прототипи

 

void f(void);

extern void f(void);

 

є еквівалентними.

 

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 заголовних файлах:

 








Дата добавления: 2014-12-26; просмотров: 889;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.014 сек.