Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих (Стенли Липпман) 3-е хххх.pdf
Скачиваний:
84
Добавлен:
30.05.2015
Размер:
5.92 Mб
Скачать

С++ для начинающих

407

}

Вложенное пространство имен является вложенной областью видимости внутри пространства, содержащего его. В процессе разрешения имен вложенные пространства ведут себя так же, как вложенные блоки. Когда некоторое имя употребляется в пространстве имен, поиск его объявление проводится во всех объемлющих пространствах. В следующем примере разрешение имени Type происходит в таком порядке: сначала ищем его в пространстве имен MatrixLib, затем в 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, упоминаемого в

MatrixLib, оно будет найдено в cplusplus_primer, поэтому у функции func()

параметр имеет тип int.

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

8.5.4. Определение члена пространства имен

Мы видели, что определение члена пространства имен может появиться внутри определения самого пространства. Например, класс matrix и константа pi появляются внутри вложенного пространства имен MatrixLib, а определения функций operator+() и inverse() приводятся где-то в другом месте текста программы:

С++ для начинающих

408

// ---- 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 & );

// ...

}

}

Член пространства имен можно определить и вне соответствующего пространства. В таком случае имя члена должно быть квалифицировано именами пространств, к которым он принадлежит. Например, если определение функции operator+() помещено в

//---- primer.C ----

#include "primer.h"

//определение в глобальной области видимости cplusplus_primer::MatrixLib::matrix

cplusplus_primer::MatrixLib::operator+

( const matrix& ml, const matrix &m2 )

глобальную область видимости, то оно должно выглядеть следующим образом:

{ /* ... */ }

Имя operator+() квалифицировано в данном случае именами пространств cplusplus_primer и MatrixLib. Однако обратите внимание на тип matrix в списке параметров operator+(): употреблено неквалифицированное имя. Как такое может быть?

В определении функции operator+() можно использовать неквалифицированные имена для членов своего пространства, поскольку определение принадлежит к его области видимости. При разрешении имен внутри функции operator+() используется MatrixLib. Заметим, однако, что в типе возвращаемого значения все же нужно указывать квалифицированное имя, поскольку он расположен вне области видимости, заданной определением функции:

cplusplus_primer::MatrixLib::operator+

В определении operator+() неквалифицированные имена могут встречаться в любом объявлении или выражении внутри списка параметров или тела функции. Например, локальное объявление внутри operator+() способно создать объект класса matrix:

С++ для начинающих

409

// ---- primer.C ----

#include "primer.h"

cplusplus_primer::MatrixLib::matrix cplusplus_primer::MatrixLib::operator+

( const matrix &ml, const matrix &m2 )

{

// объявление локальной переменной типа

// cplusplus_primer::MatrixLib::matrix matrix res;

// вычислим сумму двух объектов matrix return res;

}

Хотя члены могут быть определены вне своего пространства имен, такие определения допустимы не в любом месте. Их разрешается помещать только в пространства, объемлющие данное. Например, определение operator+() может появиться в глобальной области видимости, в пространстве имен cplusplus_primer и в

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

namespace cplusplus_primer { MatrixLib::matrix MatrixLib::operator+

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

пространстве MatrixLib. В последнем случае это выглядит так:

}

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

namespace cplusplus_primer { namespace MatrixLib {

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

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

matrix operator+ ( const matrix &ml, const matrix &m2 ); // ...

}

ошибочным, если бы ему не предшествовало объявление в файле primer.h:

}

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

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

С++ для начинающих

410

// 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) распространяется и на него. Чтобы удовлетворить этому требованию, программы, в которых используются пространства имен, обычно организуют следующим образом:

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

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

namespace cplusplus_primer { class matrix { /* ... */ }; // объявления функций

extern matrix operator+ ( const matrix &m1, const matrix &m2 ); extern void inverse( matrix & );

// объявления объектов extern bool error_state;

они используются.

}

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