Как упоминалось в разделе 16.5, в отличие от других областей видимости, пространство имен может быть определено в нескольких частях. Вот определение пространства имен:

namespace nsp {

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

}

Этот код определяет новое пространство имен nsp или добавляет члены к уже существующему. Если пространство имен nsp еще не определенно, то создается новое пространство имен с этим именем. В противном случае это определение открывает уже существующее пространство имен и добавляет в него новые объявления.

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

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

• Определения членов пространства имен могут быть помещены в отдельные файлы исходного кода.

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

Для представления несвязанных типов в составных пространствах имен следует использовать отдельные файлы.

Определение пространства имен cplusplus_primer

Используя эту стратегию для отделения интерфейса от реализации, определим библиотеку cplusplus_primer в нескольких отдельных файлах. Объявления класса Sales_data и связанных с ним функций поместим в файл заголовка Sales_data.h, а таковые для класса Query (см. главу 15) — в заголовок Query.h и т.д. Соответствующие файлы реализации были бы в таких файлах, как Sales_data.cc и Query.cc:

// ---- Sales_data.h ----

// директивы #include должны быть перед открытием пространства имен

#include

namespace cplusplus_primer {

 class Sales_data { /* ... */};

 Sales_data operator+(const Sales_data&,

                      const Sales_data&);

 // объявления остальных функций интерфейса класса Sales_data

}

// ---- Sales_data.cc ----

// все директивы #include перед открытием пространства имен

#include "Sales_data.h"

namespace cplusplus_primer {

 // определения членов класса Sales_data и перегруженных операторов

}

Использующая эту библиотеку программа включила бы все необходимые заголовки. Имена в этих заголовках определены в пространстве имен cplusplus_primer:

// ---- user.cc ----

// имена заголовка Sales_data.h находятся в пространстве

// имен cplusplus_primer

#include "Sales_data.h"

int main() {

 using cplusplus_primer::Sales_data;

 Sales_data trans1, trans2;

 // ...

 return 0;

}

Подобная организация программы придает библиотеке свойство модульности, необходимое как разработчикам, так и пользователям. Каждый класс организован в виде двух файлов: интерфейса и реализации. Пользователь одного класса вовсе не должен использовать при компиляции другие классы. Их реализацию можно скрыть от пользователей, разрешив при этом компилировать и компоновать файлы Sales_data.cc и user.cc в одну программу, причем без опасений по поводу возникновения ошибок во время компиляции или компоновки. Кроме того, разработчики библиотеки могут работать над реализацией каждого класса независимо.

В использующую эту библиотеку программу следует подключить все необходимые заголовки. Имена в этих заголовках определены в пространстве имен cplusplus_primer.

Перейти на страницу:

Похожие книги