Урок №56. Простір імен

  Юрій  | 

  Оновл. 10 Тра 2020  | 

 418

Цей урок є продовженням уроку №27.

Конфлікт імен

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

Розглянемо приклад такого конфлікту. boo.h і doo.h — це заголовки з функціями, які виконують різні речі, але мають однакові імена та параметри.

boo.h:

doo.h:

main.cpp:

Якщо boo.h і doo.h скомпілювати окремо, то все відбудеться без інцидентів. Однак, з’єднавши їх в одній програмі, ми підключимо дві різні функції, але з однаковими іменами і параметрами, в одну область видимості (глобальну), а це, в свою чергу, призведе до конфлікту імен. В результаті, компілятор видасть помилку. Ось для вирішення таких от проблем і додали в С++ таку концепцію, як простір імен.

Що таке простір імен?

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

Глобальна змінна g_z і функція boo() визначені в глобальному просторі імен.

В наведеному вище прикладі, при підключенні файлів boo.h і doo.h, обидві версії doOperation() були додані в глобальний простір імен, через що і, власне, стався конфлікт імен.

Щоб уникнути подібних ситуацій, коли два незалежних об’єкти мають ідентифікатори, які можуть конфліктувати один з одним при спільному використанні, C++ дозволяє оголошувати власні простори імен через ключове слово namespace. Все, що оголошено всередині користувацького простору імен, належить тільки цьому простору імен (а не глобальному).

Перепишемо заголовкові файли з прикладу вище, але уже з використанням простору імен:

boo.h:

doo.h:

Тепер doOperation() з файлу boo.h знаходиться в просторі імен Boo, а doOperation() з файлу doo.h — в просторі імен Doo. Подивимося, що станеться при перекомпіляції main.cpp:

Результатом буде ще одна помилка:

C:\VCProjects\Test.cpp(15) : error C2065: 'doOperation' : undeclared identifier

Сталося так, що коли ми спробували викликати функцію doOperation(), компілятор заглянув в глобальний простір імен в пошуках визначення doOperation(). Однак, оскільки жодна з наших версій doOperation() не перебуває у глобальному просторі імен, компілятор просто не зміг знайти визначення doOperation() взагалі!

Існує два різні способи повідомити компілятору, яку версію doOperation() слід використовувати: через оператор дозволу області видимості або за допомогою стейтментів using (про них ми поговоримо в наступному уроці).

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

Перший спосіб вказати компілятору шукати ідентифікатор в певному просторі імен — це використати назву необхідного простору імен + оператор дозволу області видимості (::) + необхідний ідентифікатор.

Наприклад, повідомимо компілятору використовувати версію doOperation() з простору імен Boo:

Результат:

9

Якщо б ми захотіли використовувати версію doOperation() з простору імен Doo:

Результат:

1

Оператор дозволу області видимості дозволяє вибрати конкретний простір імен. Ми навіть можемо зробити наступне:

Результат:

9
1

Також цей оператор можна використовувати без будь-якого префіксу (наприклад, ::doOperation). В такому випадку ми посилаємося на глобальний простір імен.

Простори імен з однаковими іменами

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

add.h:

subtract.h:

main.cpp:

Все працює, як потрібно.

Стандартна бібліотека C++ широко використовує цю особливість, оскільки всі заголовки, які знаходяться в ній, реалізовують свій функціонал всередині простору імен std.

Псевдоніми і вкладені простори імен

Одні простори імен можуть бути вкладені в інші простори імен. Наприклад:

Зверніть увагу, оскільки Doo знаходиться всередині Boo, то доступ до g_x здійснюється через Boo::Doo::g_x.

Так як це не завжди зручно і ефективно, то C++ дозволяє створювати псевдоніми для просторів імен:

Варто відзначити, що простори імен в C++ не були розроблені як спосіб реалізації інформаційної ієрархії — вони були розроблені як механізм запобігання виникненню конфліктів імен. Як доказ цьому, вся Стандартна бібліотека шаблонів знаходиться в єдиному просторі імен std::.

Вкладеність просторів імен не рекомендується використовувати, так як це розсадник помилок при невмілому використанні + додаткове ускладнення логіки програми.

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (3 оцінок, середня: 5,00 з 5)
Loading...

Залишити відповідь

Ваш E-mail не буде опублікований. Обов'язкові поля відмічені *