Пространства имен
Пространства имен позволяют снизить риск конфликта имен в программах С++. Конфликты имен часто возникают в больших программах, использующих несколько библиотек независимых разработчиков. В своей собственной программе вы решаете сами, использовать ли вам или нет пространства имен.
Обычно в пространство имен заключаются все объявления заголовочного файла, чтобы гарантировать невозможность попадания идентификаторов, объявленных в этом заголовочном файле, в глобальное пространство имен. Например:
01 #ifndef SOFTWAREINC_RANDOM_H
02 #define SOFTWAREINC_RANDOM_H
03 namespace SoftwareInc
04 {
05 extern int randomNumbers[128];
06 void populateRandomArray();
07 }
08 #endif
(Обратите внимание на то, что мы переименовали препроцессорные макросимволы, используемые для предотвращения многократного включения содержимого заголовочного файла, снижая риск конфликта имен с заголовочным файлом, имеющим такое же имя, но расположенным в другом каталоге.)
Синтаксис пространства имен совпадает с синтаксисом класса, однако в конце не ставится точка с запятой. Ниже приводится новая версия файла random.cpp:
01 #include "random.h"
02 int SoftwareInc::randomNumbers[128];
03 static int seed = 42;
04 static int nextRandomNumber()
05 {
06 seed = 1009 + (seed * 2011);
07 return seed;
08 }
09 void SoftwareInc::populateRandomArray()
10 {
11 for (int i = 0; i < 128; ++i)
12 randomNumbers[i] = nextRandomNumber();
13 }
В отличие от классов, пространства имен можно «повторно открывать» в любое время. Например:
01 namespace Alpha
02 {
03 void alpha1();
04 void alpha2();
05 }
06 namespace Beta
07 {
08 void beta1();
09 }
10 namespace Alpha
11 {
12 void alpha3();
13 }
Это позволяет определять сотни классов, размещенных во многих заголовочных файлах и принадлежащих одному пространству имен. Используя этот прием, стандартная библиотека С++ помещает все свои идентификаторы в пространство имен std. В Qt пространства имен используются для таких подобных глобальным идентификаторов, как Qt::AlignBottom и Qt::yellow. По историческим причинам классы Qt не принадлежат никакому пространству имен, но имеют префикс 'Q'.
Для ссылки на идентификатор, объявленный в другом пространстве имен, указывается префикс в виде имени этого пространства имен (и ::). Можно поступить по-другому — использовать один из следующих трех механизмов, нацеленных на уменьшение количества вводимых символов:
• Можно определить псевдоним пространства имен:
namespace ElPuebloDeLaReinaDeLosAngeles
{
void beverlyHills();
void culverCity();
void malibu();
void santaMonica();
}
namespace LA = ElPuebloDeLaReinaDeLosAngeles;
После определения псевдонима он может использоваться вместо исходного имени.
• Из пространства имен можно импортировать один идентификатор:
int main()
{
using ElPuebloDeLaReinaDeLosAngeles::beverlyHills;
beverlyHills();
}
Объявление using позволяет обращаться к данному идентификатору без указания префикса, состоящего из имени пространства имен.
• Можно импортировать все пространство имен с помощью одной директивы:
int main()
{
using namespace ElPuebloDeLaReinaDeLosAngeles;
santaMonica();
malibu();
}
При таком подходе конфликты имен становятся более вероятными. Если компилятор «жалуется» на двусмысленное имя (например, когда два класса имеют одинаковое имя, определенное в различных пространствах имен), всегда при ссылке на идентификатор его можно уточнить именем пространства имен.