Читайте также:
|
|
Пространства имен (namespaces) были введены в стандарт C++ в 1995г. Пространство имен – это именованная область действия имен.
Пространство имен дают возможность собрать в одну группу некоторые определения глобальных классов, объектов и/или функций под определенным именем. Говоря по- другому, они позволяют расщепить глобальную область действия на именованные подобласти, известные как namespaces. Синтаксически это пишется:
namespace identifier
{
namespace-body
} // точка с запятой не нужна !
Здесь, identifier – любой верный идентификатор, а namespace-body - набор классов, объектов и функций, которые включаются в данное пространство имен. Например:
namespace general{ int A, B;}В этом случае, A и B - обычные переменные, объединенные в пространство имен с именем general. Для доступа к этим переменным извне мы должны использовать операцию :: . Например:
general::A
general::B
Пространства имен особенно полезны в случаях, когда существует опасность, что глобальный объект или функция имеют те же имена, что и у некоторых других объектов, вызывая тем самым ошибку переопределения имен. Например:
// namespaces#include <iostream.h>namespace first{ int var = 5;}namespace second{ double var = 3.1416;}int main () { cout << first::var << endl; cout << second::var << endl; return 0;
}
Здесь конфликта имен нет, поскольку идентификаторы var – из разных пространств имен.
Для того, чтобы понять причины введения в С++ понятия пространства имен и связанных с ним механизмов, можно провести аналогию с файловой системой. Вообразим, что файловая система нашего компьютера не имеет каталогов и подкаталогов. Тогда все файлы содержались бы в некотором “плоском” хранилище, доступные в любой момент времени для любого пользователя и любого приложения. В результате, возникли бы всякого рода трудности: ограничения на длину имен файлов может привести к конфликту этих имен; простые действия вроде копирования, просмотра и поиска файлов стали бы более занудливыми и т. п., не говоря уже об авторизации и секретности.
Пространства имен, в определенном смысле, эквивалентны каталогам (директориям). Они могут быть вложенными, они защищают код программы от конфликтов имен, они дают нам возможность скрыть объявления объектов, и они не вызывают никаких накладных расходов в памяти и во время выполнения программы. Большинство компонентов стандартной библиотеки C++ собраны в группу – пространство имен std . Пространство имен std подразделяется на дополнительные пространства, например, std::rel_ops , которое содержит определения перегружаемых операций STL.
Итак, идентификаторы, используемые в коде стандартной библиотеки, содержатся в предопределенном пространстве имен std. Можно говорить, что они принадлежат пространству std. Каждый заголовочный файл стандартной библиотеки добавляет свои идентификаторы (==имена) в std.
Код нашей программы, в общем случае, не принадлежит пространству std. Поэтому, чтобы использовать функции вывода, описанные в заголовке < iostream>, мы должны сообщить компилятору, что эти функции принадлежат (в обсуждаемом нами смысле) пространству имен std. Делается это с помощью директивы using:
using namespace std;
Вот пример:
Пример 3-1.
#include <iostream>
using namespace std;
namespace my_space
{
int count;
const int size = 10;
const double pi = 3.14;
void print();
namespace inner
{ int count; }
}void my_space::print()
{
cout << "Name space demo:\n";
cout << "size = " << size << endl; // без спецификатора пространства имен
cout << "pi = " << pi << endl;
cout << "Inner::count = " << inner::count; // спецификатор "inner::"
}
int main()
{
const int size = 5;
int table[my_space::size][size];
for (my_space::count = 0; my_space::count < my_space::size; ++ my_space::count)
{
for (my_space::inner::count = 0; my_space::inner::count < size; ++my_space::inner::count)
{
table[my_space::count][ my_space::inner::count]
= my_space::pi * my_space::count * my_space::inner::count;
}
}
return 0;
}
Глобальное пространство имен может быть анонимным, т.е., без имени (имя не указывается, и компилятор дает этому пространству имя, совпадающее с именем файла). Идентификаторы такого пространства имен известны только в том файле, где пространство определено (эффект такой же, как при определении идентификатора с ключевым словом static).
И, наконец, несколько общих замечаний об использовании пространств имен (см. Т. Павловская):
В объявлении поименованной области могут присутствовать как объявления, так и определения. Логично помещать в нее только объявления, а определять их позднее с помощью имени области и оператора доступа к области видимости ::, например (предполагается, что речь идет о пространстве имен с названием demo):
void demo::func1(int) { /*... */}
Этот синтаксис применяется для разделения интерфейса ( объявления ) и реализации (определения). Таким способом нельзя объявить новый элемент пространства имен (так у Павловской! Однако, Лафоре(стр.611) пишет: “Объявления можно помещать и вне пространства имен, и они будут работоть, как если бы они были внутри него” -> проверьте!).
Новые, т.е. дополнительные, имена (объекты) могут быть введены с помощью повторного (многократного) определения некоторого пространства имен. Хотя это будет выглядеть как переопределение пространства, но, на самом деле, мы просто наращиваем уже определенное пространство имен.
Объекты, объявленные внутри области, являются видимыми с момента объявления. К ним можно явно обращаться с помощью имени области и оператора доступа к области видимости ::, например:
demo::i = 100; demo::func2(10);
Если имя часто используется вне своего пространства, можно объявить его доступным с помощью директивы (оператора) using:
using demo::i;
После этого можно использовать имя без явного указания области.
Если требуется сделать доступными все имена из какой-либо области, используется оператор using namespace:
using namespace demo;
Операторы using и using namespace можно использовать и внутри объявления поименованной области, чтобы сделать в ней доступными объявления из другой области:
namespace Department_of_Maths{
using demo::i;
//...
}
Имена, объявленные в поименованной области явно или с помощью оператора using, имеют приоритет по отношению к именам, объявленным с помощью оператора using namespace (это имеет значение при включении нескольких поименованных областей, содержащих совпадающие имена).
Директива using обычно делает пространство имен видимым начиная с места ее написания и до конца. Можно сузить область действия директивы до блока, используя ее, например, в теле функции, так что вне функции элементы пространства будут недоступны.
(2) Связывание (Компоновка – Linkage)
C++ допускает различные возможности для размещения данных в памяти. Обычно, Вам нужно выбрать: как долго данные остаются в памяти (время существования объекта), из каких частей программы будет иметься доступ к данным (видимость объекта и связывание). Пространства имен обеспечивают дополнительный контроль и управление при доступе к объектам программы. Большие программы состоят из многих файлов с исходным кодом, которые могут совместно использовать некоторые общие данные. Такие программы, в типичном случае, компилируются раздельно по файлам-модулям, а затем выполняется их сборка (компоновка и построение).
Если программа состоит из нескольких исходных файлов, то глобальные идентификаторы функций (за исключением inline -функций) и переменных (но не константы или typedef -имена), объявленные в некотором файле, остаются действующими в других файлах той же программы. Один и тот же идентификатор не нужно повторно определять. Глобальный идентификатор функции или переменной, определенные в одном исходном файле, доступен из другого файла через ссылочное объявление с помощью ключевого слова extern. Ключевое слово говорит компилятору, что переменная будет определена где-то – возможно в этом же файле, а может быть и в другом.
В файле 1:
int x = 10;
void func (int x) { /* какой-то код */}
в файле 2:
extern int x;
extern void func(int);
Константная переменная может быть сделана доступной из другого файла, если она объявлена как extern, а другой файл содержит ссылочное объявление:
В файле 1:
extern const float pi = 3.14;
в файле 2:
extern const float pi;
Дата добавления: 2015-11-16; просмотров: 50 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Ii) Инициализация указателей | | | Еще о классе памяти |