Выбрать главу

#include "primer.h"

namespace cplusplus_primer {

MatrixLib::matrix MatrixLib::operator+

( const matrix ml, const matrix m2 ) { /* ... */ }

}

Член может определяться вне своего пространства только при условии, что ранее он был объявлен внутри. Последнее приведенное определение operator+() было бы ошибочным, если бы ему не предшествовало объявление в файле primer.h:

namespace cplusplus_primer {

namespace MatrixLib {

class matrix { /*...*/ };

// следующее объявление не может быть пропущено

matrix operator+ ( const matrix ml, const matrix m2 );

// ...

}

}

8.5.5. ПОО и члены пространства имен

Как уже было сказано, определение пространства имен может состоять из разрозненных частей и размещаться в разных файлах. Следовательно, член пространства разрешено объявлять во многих файлах. Например:

// primer.h

namespace cplusplus_primer {

// ...

void inverse( matrix );

}

// usel.C

#include "primer.h"

// объявление cplusplus_primer::inverse() в use1.C

// use2.C

#include "primer.h"

// объявление cplusplus_primer::inverse() в use2.C

Объявление cplusplus::inverse() в primer.h ссылается на одну и ту же функцию в обоих исходных файлах use1.C и use2.C.

Член пространства имен является глобальной сущностью, хотя его имя квалифицировано. Требование ПОО (правило одного определения, см. раздел 8.2) распространяется и на него. Чтобы удовлетворить этому требованию, программы, в которых используются пространства имен, обычно организуют следующим образом:

Объявления функций и объектов, являющихся членами пространства имен, помещают в заголовочный файл, который включается в каждый исходный файл, где они используются.

// ---- primer.h ----

namespace cplusplus_primer {

class matrix { /* ... */ };

// объявления функций

extern matrix operator+ ( const matrix m1, const matrix m2 );

extern void inverse( matrix );

// объявления объектов

extern bool error_state;

}

*

* Определения этих членов помещают в исходный файл, содержащий реализацию:

// ---- primer.C ---- #include "primer.h"

namespace cplusplus_primer {

// определения функций

void inverse( matrix )

{ /* ... */ }

matrix operator+ ( const matrix ml, const matrix m2 )

{ /" ... */ }

// определения объектов

bool error_state = false;

}

Для объявления объекта без его определения используется ключевое слово extern, как и в случае такого объявления в глобальной области видимости.

8.5.6. Безымянные пространства имен

Может возникнуть необходимость определить объект, функцию, класс или любую другую сущность так, чтобы она была видимой только в небольшом участке программы. Это еще один способ решения проблемы засорения глобального пространства имен. Поскольку мы уверены, что эта сущность используется ограниченно, можно не тратить время на выдумывание уникального имени. Если мы объявляем объект внутри функции или блока, его имя видимо только в этом блоке. А как сделать некоторую сущность доступной нескольким функциям, но не всей программе?

Предположим, мы хотим реализовать набор функций для сортировки вектора типа double:

// ----- SortLib.h -----

void quickSort( double *, double * );

void bubbleSort( double *, double * );

void mergeSort( double *, double * );

void heapSort( double *, double * );

Все они используют одну и ту же функцию swap() для того, чтобы менять местами элементы вектора. Однако она не должна быть видна во всей программе, поскольку нужна только четырем названным функциям. Локализуем ее в файле SortLib.C. Приведенный код не дает желаемого результата. Как вы думаете, почему?

// ----- SortLib.C -----

void swap( double *dl, double *d2 ) { /* ... */ }

// только эти функции используют swap()

void quickSort( double *d1, double *d2 ) { /* ... */ }

void bubbleSort( double *d1, double *d2 ) { /* ... */ }

void mergeSort( double *d1, double *d2 ) { /* ... */ }

void heapSort( double *d1, double *d2 ) { /* ... */ }

Хотя функция swap() определена в файле SortLib.C и не появляется в заголовочном файле SortLib.h, где содержится описание интерфейса библиотеки сортировки, она объявлена в глобальной области видимости. Следовательно, это имя является глобальным, при этом сохраняется возможность конфликта с другими именами.

Язык С++ предоставляет возможность использования безымянного пространства имен для объявления сущности, локальной по отношению к файлу. Определение такого пространства начинается ключевым словом namespace. Очевидно, что никакого имени за этим словом нет, а сразу же идет блок в фигурных скобках, содержащий различные объявления. Например: