Заява використання простору імен std зазвичай вважається поганою практикою. Альтернативою цьому оператору є визначення простору імен, до якого належить ідентифікатор, за допомогою оператора області видимості (::) кожного разу, коли ми оголошуємо тип.
Хоча заява позбавляє нас від друкування std:: щоразу, коли ми хочемо отримати доступ до класу або типу, визначеного в просторі імен std, він імпортує весь файл станд простір імен у поточний простір імен програми. Давайте наведемо кілька прикладів, щоб зрозуміти, чому це може бути не так добре
Скажімо, ми хочемо використати cout із простору імен std. Так і пишемо
приклад 1:
CPP
#include> using> namespace> std;> > cout <<>' Something to Display'>;> |
>
>
Тепер на більш пізньому етапі розробки ми хочемо використати іншу версію cout, реалізовану на замовлення в деякій бібліотеці під назвою foo (наприклад)
що таке f5 на клавіатурі
CPP
#include> #include> using> namespace> std;> > cout <<>' Something to display'>;> |
>
>
Зауважте, що зараз є неоднозначність, на яку бібліотеку вказує cout? Компілятор може виявити це і не скомпілювати програму. У гіршому випадку програма може скомпілюватися, але викликати неправильну функцію, оскільки ми ніколи не вказували, до якого простору імен належить ідентифікатор.
Простори імен були введені в C++ для вирішення конфліктів імен ідентифікаторів. Це гарантувало, що два об’єкти можуть мати однакові назви, але при цьому оброблятися по-різному, якщо вони належать до різних просторів імен. Зверніть увагу, як у цьому прикладі сталося прямо протилежне. Замість вирішення конфлікту імен ми створюємо конфлікт імен.
Коли ми імпортуємо простір імен, ми фактично перетягуємо всі визначення типів у поточну область. Простір імен std величезний. У ньому є сотні попередньо визначених ідентифікаторів, тому розробник може не помітити той факт, що в бібліотеці std є інше визначення запланованого об’єкта. Не знаючи про це, вони можуть продовжити вказувати свою власну реалізацію та очікувати, що вона буде використана в наступних частинах програми. Таким чином, існуватимуть два визначення для одного типу в поточному просторі імен. Це заборонено в C++, і навіть якщо програма компілюється, неможливо дізнатися, яке визначення де використовується.
Рішення проблеми полягає в тому, щоб явно вказати, до якого простору імен належить наш ідентифікатор, використовуючи оператор області (::). Таким чином, одним із можливих рішень наведеного вище прикладу може бути
CPP
як перетворити рядок на int
#include> #include> > // Use cout of std library> std::cout <<>'Something to display'>;> > // Use cout of foo library> foo::cout <>'Something to display'>;> |
>
>
Але доводиться друкувати std:: кожен раз, коли ми визначаємо тип, це втомливо. Це також робить наш код більш заплутаним із великою кількістю визначень типів і ускладнює читання коду. Розглянемо для прикладу код отримання поточного часу в програмі
приклад 2:
CPP
#include> #include> > auto> start = std::chrono::high_performance_clock::now()> > // Do Something> > auto> stop> >= std::chrono::high_peformance_clock::now();> auto> duration> >= std::duration_cast(stop - start);> |
>
>
Вихідний код, усіяний складними та довгими визначеннями типів, не дуже легкий для читання. Це те, чого розробники прагнуть уникати, оскільки для них дуже важлива зручність коду.
Є кілька способів вирішити цю дилему, тобто вказати точний простір імен без засмічення коду ключовими словами std.
Розгляньте можливість використання typedefs
typedef позбавляє нас від написання довгих визначень типів. У нашому прикладі 1 ми могли б вирішити проблему, використовуючи два typedef, один для бібліотеки std, а інший для foo
CPP
#include> #include> > typedef> std::cout cout_std;> typedef> foo::cout cout_foo;> > cout_std <<>'Something to write'>;> cout_foo <<>'Something to write'>;> |
>
>
Замість того, щоб імпортувати цілі простори імен, імпортуйте скорочений простір імен
У прикладі 2 ми могли імпортувати лише простір імен chrono під std.
CPP
рядок n java
#include> #include> > // Import only the chrono namespace under std> using> std::chrono;> > auto> start = high_performance_clock::now();> > // Do Something> auto> stop = high_performance_clock::now();> auto> duration duration_cast(stop - start);> |
>
>
Ми також можемо використовувати оператор для імпорту одного ідентифікатора. Щоб імпортувати лише std::cout, ми можемо використовувати
using std::cout;>
Якщо ви все одно імпортуєте цілі простори імен, спробуйте зробити це всередині функцій або обмеженої області, а не в глобальній області.
Використовуйте оператор using namespace std у визначеннях функцій або класів, структур. При цьому визначення простору імен імпортуються в локальну область, і ми принаймні знаємо, звідки можуть виникнути можливі помилки, якщо вони виникнуть.
CPP
#include> > // Avoid this> using> namespace> std;> > void> foo()> {> >// Inside function> >// Use the import statement inside limited scope> >using> namespace> std;> > >// Proceed with function> }> |
>
масив сортування в java
>
Висновок.
Ми обговорили альтернативні методи доступу до ідентифікатора з простору імен. У всіх випадках уникайте імпорту цілих просторів імен у вихідний код.
Незважаючи на те, що для вивчення та розвитку хороших практик програмування може знадобитися деякий час, вони, як правило, окупаються в довгостроковій перспективі. Написання чистого, однозначного та надійного коду без помилок має бути метою будь-якого розробника програм.