Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Липпман.doc
Скачиваний:
8
Добавлен:
14.08.2019
Размер:
7.54 Mб
Скачать

8.5.3. Вложенные пространства имен

Мы уже упоминали, что пользовательские пространства имен могут быть вложенными. Такие пространства применяются для дальнейшего структурирования кода нашей библиотеки. Например:

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

namespace cplusplus_primer {

// первое вложенное пространство имен:

// матричная часть библиотеки

namespace MatrixLib {

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

const double pi = 3.1416;

matrix operators+ ( const matrix &ml, const matrix &m2 );

void inverse( matrix & );

// ...

}

// второе вложенное пространство имен:

// зоологическая часть библиотеки

namespace AnimalLib {

class ZooAnimal { /* ... */ };

class Bear : public ZooAnimal { /* ... */ };

class Raccoon : public Bear { /* ... */ };

// ...

}


}

Пространство имен cplusplus_primer содержит два вложенных: MatrixLib и AnimalLib.

cplusplus_primer предотвращает конфликт между именами из нашей библиотеки и именами из глобального пространства вызывающей программы. Вложенность позволяет делить библиотеку на части, в которых сгруппированы связанные друг с другом объявления и определения. MatrixLib содержит сущности, имеющие отношение к классу matrix, а AnimalLib – к классу ZooAnimal.

Объявление члена вложенного пространства скрыто в этом пространстве. Имя такого члена автоматически дополняется поставленными спереди именами самого внешнего и вложенного пространств.

Например, класс, объявленный во вложенном пространстве MatrixLib, имеет имя

cplusplus_primer::MatrixLib::matrix

а функция

cplusplus_primer::MatrixLib::inverse

Программа, использующая члены вложенного пространства cplusplus_primer::Matrix­Lib, выглядит так:

#include "primer.h"

// да, это ужасно...

// скоро мы рассмотрим механизмы, облегчающие

// использование членов пространств имен!

void func( cplusplus_primer::MatrixLib::matrix &m )

{

// ...

cplusplus_primer::MatrixLib::inverse( m );

return m;


}

Вложенное пространство имен является вложенной областью видимости внутри пространства, содержащего его. В процессе разрешения имен вложенные пространства ведут себя так же, как вложенные блоки. Когда некоторое имя употребляется в пространстве имен, поиск его объявление проводится во всех объемлющих пространствах. В следующем примере разрешение имени Type происходит в таком порядке: сначала ищем его в пространстве имен Ma­trixLib, затем в cplusplus_primer и наконец в глобальной области видимости:

typedef double Type;

namespace cplusplus_primer {

typedef int Type; // скрывает ::Type

namespace MatrixLib {

int val;

// Type: объявление найдено в cplusplus_primer

int func(Type t) {

double val; // скрывает MatrixLib::val

val = ...;

}

// ...

}


}

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

В предыдущем примере имя Type из глобальной области видимости скрыто объявлением Type в пространстве cplusplus_primer. При разрешении имени Type, упоминаемого в Ma­trixLib, оно будет найдено в cplusplus_primer, поэтому у функции func() параметр имеет тип int.

Аналогично сущность, объявленная в пространстве имен, скрывается одноименной сущностью из вложенной локальной области видимости. В предыдущем примере имя val из Ma­trixLib скрыто новым объявлением val. При разрешении имени val внутри func() будет найдено его объявление в локальной области видимости, и потому присваивание в func() относится именно к локальной переменной.