namespace cplusplus_primer {
class matrix { /* ... */ };
void inverse ( matrix );
matrix operator+ ( const matrix ml, const matrix m2 )
{/* ... */ }
const double pi = 3.1416;
}
Именем класса, объявленного в пространстве cplusplus_primer, будет
cplusplus_primer::matrix
Именем функции
cplusplus_primer::inverse()
Именем константы
cplusplus_primer::pi
Имя класса, функции или константы расширяется именем пространства, в котором они объявлены. Такие имена называют квалифицированными.
Определение пространства имен не обязательно должно быть непрерывным. Например, предыдущее пространство могло быть определено таким образом:
namespace cplusplus_primer {
class matrix { /* ... */ };
const double pi = 3.1416;
}
namespace cplusplus_primer {
void inverse ( matrix );
matrix operator+ ( const matrix ml, const matrix m2 )
{/* ... */ }
}
Два приведенных примера эквивалентны: оба задают пространство имен cplusplus_primer, содержащее класс matrix, функцию inverse(), константу pi и operator+(). Определение пространства имен может состоять из нескольких соединенных частей.
Последовательность
namespace namespace_name {
задает новое пространство, если имя namespace_name не совпадает с одним из ранее объявленных. В противном случае новые объявления добавляются в старое пространство.
Возможность разбить пространство имен на несколько частей помогает при организации библиотеки. Ее исходный код легко разделить на интерфейсную часть и реализацию. Например:
// Эта часть пространства имен
// определяет интерфейс библиотеки
namespace cplusplus_primer {
class matrix { /* ... */ };
const double pi = 3.1416;
matrix operator+ ( const matrix ml, const matrix m2 );
void inverse ( matrix );
}
// Эта часть пространства имен
// определяет реализацию библиотеки
namespace cplusplus_primer {
void inverse ( matrix m )
{ /* ... */ }
matrix operator+ ( const matrix ml, const matrix m2 )
{ /* ... */ }
}
Первая часть пространства имен содержит объявления и определения, служащие интерфейсом библиотеки: определения типов, констант, объявления функций. Во второй части находятся детали реализации, то есть определения функций.
Еще более полезной для организации исходного кода библиотеки является возможность разделить определение одного пространства имен на несколько файлов: эти определения также объединяются. Наша библиотека может быть устроена следующим образом:
// ---- primer.h ----
namespace cplusplus_primer {
class matrix { /*... */ };
const double pi = 3.1416;
matrix operator+ ( const matrix m1, const matrix m2 );
void inverse( matrix );
}
// ---- primer.C ----
#include "primer.h"
namespace cplusplus_primer {
void inverse( matrix m )
{ /* ... */ }
matrix operator+ ( const matrix m1, const matrix m2 )
{ /* ... */ }
}
Программа, использующая эту библиотеку, выглядит так:
// ---- user.C ----
// определение интерфейса библиотеки
#include "primer.h"
void func( cplusplus_primer::matrix m )
{
//...
cplusplus_primer: :inverse( m );
return m;
}
Подобная организация программы обеспечивает модульность библиотеки, необходимую для сокрытия реализации от пользователей, в то же время позволяя без ошибок скомпилировать и связать файлы primer.C и user.C в одну программу.
8.5.2. Оператор разрешения области видимости
Имя члена пользовательского пространства дополняется поставленным спереди именем этого пространства и оператором разрешения области видимости (::). Использование неквалифицированного члена, например matrix, является ошибкой. Компилятор не знает, к какому объявлению относится это имя:
// определение интерфейса библиотеки
#include "primer.h"
// ошибка: нет объявления для matrix
void func( matrix m );
Объявление члена пространства имен скрыто в своем пространстве. Если мы не укажем компилятору, где именно искать объявление, он произведет поиск только в текущей области видимости и в областях, включающих текущую. Допустим, если переписать предыдущую программу так:
// определение интерфейса библиотеки
#include "primer.h"
class matrix { /* пользовательское определение */ };
// правильно: глобальный тип matrix найден