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

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

403

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

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

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

404

// определение интерфейса библиотеки

#include "primer.h"

class matrix { /* пользовательское определение */ };

// правильно: глобальный тип matrix найден

void func( matrix &m );

то определение класса matrix компилятор находит в глобальной области видимости и программа компилируется без ошибок. Поскольку объявление matrix как члена пространства имен cplusplus_primer скрыто в этом пространстве, оно не конфликтует с классом, объявленным в глобальной области видимости.

Именно поэтому мы говорим, что пространства имен решают проблему засорения глобального пространства: имена их членов невидимы, если имя пространства не указано явно, с помощью оператора разрешения области видимости. Существуют и другие механизмы, позволяющие сделать объявление члена пространства имен видимым вне его. Это using-объявления и using-директивы. Мы рассмотрим их в следующем разделе.

Отметим, что оператор области видимости может быть использован и для того, чтобы сослаться на элемент глобального пространства имен. Поскольку это пространство не имеет имени, запись

::member_name

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

Следующий пример демонстрирует использование оператора области видимости для обращения к скрытому члену глобального пространства имен. Функция вычисляет последовательность чисел Фибоначчи. В программе два определения переменной max. Глобальная переменная указывает максимальное значение элемента последовательности, при превышении которого вычисление прекращается, а локальная желаемую длину последовательности при данном вызове функции. (Напоминаем, что параметры функции относятся к ее локальной области видимости.) Внутри функции должны быть доступны обе переменных. Однако неквалифицированное имя max ссылается на локальное объявление этой переменной. Чтобы получить глобальную переменную, нужно использовать оператор разрешения области видимости ::max. Вот текст программы:

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

405

#include <iostream> const int max = 65000;

const int lineLength = 12;

void fibonacci( int max )

{

if ( max < 2 ) return; cout << "0 1 ";

int v1 = 0, v2 = 1, cur;

for ( int ix = 3; ix <= max; ++ix ) { cur = v1 + v2;

if ( cur > ::max ) break; cout << cur << " ";

vl = v2; v2 = cur;

if (ix % "lineLength == 0) cout << end"!;

}

}

#include <iostream> void fibonacci( int ); int main() {

cout << "Числа Фибоначчи: 16\n"; fibonacci( 16 );

return 0;

Так выглядит функция main(), вызывающая fibonacci():

}

Результат работы программы:

Числа

Фибоначчи: 16

34 55 89

0

1 1

2 3 5

8 13

21

144 233 377

610

 

 

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

Мы уже упоминали, что пользовательские пространства имен могут быть вложенными.

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

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

406

// ---- 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

Программа,

использующая

члены

вложенного

пространства

#include "primer.h"

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

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

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

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

{

// ...

cplusplus_primer::MatrixLib::inverse( m ); return m;

cplusplus_primer::MatrixLib, выглядит так: