
Программирование / ЛАБ.РАБОТЫ_С++_2012 / ЛАБ_14 / Задачи к лаб.раб.14_ПРОСТРАНСТВА ИМЕН
.doc
ПРОСТРАНСТВА ИМЕН
Учитывая большое количество в языке С++ библиотек, функций (особенно), насыщенностью текстов программ именами, отражающими типовые процессы (классы, переменные) проблема выбора имен, требование к их разнообразию при описании одинаковых предметов, событий и прочее приобретает особую важность. В последних версиях языка С++ эта проблема решается введением механизма пространства имен (namespace). Создание пользователем различных пространств имен допускает использование одинаковых имен в одной программе, но находящихся в различных разделенных пространствам. При этом отпала необходимость определять имена в глобальном пространстве, т.е. работать с глобальными переменными, что, как известно, не эффективно с точки зрения оптимального использования оперативной памяти.
Для стандартной библиотеки закреплено свое имя пространства имен std.
Пространство имен ограничивает область видимости. Размещенные в этой области имена вне этой области невидимы (недостижимы ). Описание пространства имен можно представит в виде специальной функции. Используя грамматику языка Бэкуса-Наури эту функцию можно представить в виде (имена пространств имен будем обозначать (называть) ns1, ns2, …, nsi):
[ using] namespace [ имя пространства ] [ :: имя функц/переменной][, имя функ/переем. …]
[ {
// Объявления
} ]]
Приведем используемые типовые структуры описания пространства имен.
1) namespace { // объявления } – безымянное пространство имен, видимость которых ограничена файлом.
2) namespace ns1 { // объявления } - именное пространство имен
3) namespace ns1 { // объявления } – совокупность отдельных
namespace ns2 { // объявления } пространств имен
- - - - - - - - - - - - - - - - - - - - - - - - - -
namespace nsi { // объявления }
4) namespace ns1 - вложенные пространства имен
{ // объявления
namespace ns2
{ // объявления
- - - - - - - - - - - - -
namespace nsi
{ // объявления
}
}
}
5)using namespace std;- полное пространство имен, применяемых в библиотеке std.
6) using std :: отдельное имя из библиотеки std; // cout, cin, left, hex, showpos и др..
7) std :: отдельное имя - имя, применяемое в библиотеке std.
Общее положение: если имя, например w (функции, переменной, параметра), объявлено в области пространства имен с именем nsk, то обращение к этому имени в этой же области производится по имени w. При обращении к этому имени в другой области структура обращения имеет вид nsk::w, где имя nsk выполняет роль квалификатора (меткой пространства имен) соответствующего имени.
Применяемые одновременно различные пространства имен не перекрывают друг друга. Поэтому всегда существуют глобальное пространство имен (для глобальных переменных) и все дополнительные пространства имен.
Применение пространства имен рассмотрим на примере программы вида
#include <iostream>
int f()
{ int if, jf, kf;
if = jf = kf = 3;
}
int main ()
{ int im, jm, km;
cout<<” if= ”<<if<<” ig= ”<<ig<<” im= ”<<im<<” “<<”\n”;
}
int g()
{ int ig, jg, kg;
ig = jg = kg =5;
}
Остановимся подробнее на применении описанных структур.
1) Приведенный ниже текст программы (пример 1) демонстрирует работу с применением безымянного пространства имен. В тексте программы не используется пространство имен стандартной библиотеки std. Для этого закомментированы следующие строки
// #include <iostream>
// using namespace std;
// cout<<”\n mi= ”<<mi<<”\n”;
Отмечено, что по умолчанию #include “stdafx.h” включает библиотеку <stdio.h>
Для работы программы следует удалить комментарии /* 1 1*/ и оставить везде комментарии // 2 . При этом работает механизм безымянного пространства имен.
Пример 1
2) Имя пространства имен является квалификатором, который используется для сопровождения отдельных имен, объявленных в выделенном пространстве имен. Ниже приведен текст программы, рассмотренный в примере 1, но с применением имени пространства имен ns1.
Полученный текст программы представлен в виде двух примеров:
-
примера 2_1 - с пространством имен, не включающим функции f() и g();
-
примера 2_2 - с пространством имен, включающим функции f() и g().
Сравнение двух этих программ наглядно демонстрирует механизм описания переменных с применением названий пространства имен.
Пример 2_1_(2)
Пример 2_2_(3)
3) При рассмотрении нескольких отдельных пространств имен рассматривается пример предыдущей задачи с двумя пространствами имен ns1 и ns2 и с разделением одного пространства имен (например ns1) на несколько частей в одном файле.
В примере 3_1 демонстрируется применение двух непересекающихся пространств имен ns1 и ns2 и организация добавления этих имен к соответствующим именам в тексте программы (ns1 ->f(), ns2 ->mi, g()).
Пример 3_1_(4)
Разделение одного пространства имен на несколько частей с одним именем даже в одном файле показано в примере 3_2. Из сравнения текста программы примера 3_1 и текста программы примера 3_2 видно, что в последнем случае везде имя ns2 было заменено на имя ns1.
Полученный результат позволяет сделать важный вывод о возможности размещения различных фрагментов одного пространства имени (с одинаковыми именами) в различных участках программы (но не внутри функций). Особый интерес представляет размещение этих фрагментов в разных файлах одной программы.
Пример 3_2_(5)
4) Различные пространства имен могут быть вложены друг в друга. Ниже рассматривается текст программы, в котором пространство имен ns2 вложено в пространство имен ns1. Как видно, в этом случае для обращения к именам, относящихся к вложенным пространствам имен, следует добавлять цепочку имен пространств имен, начиная с внешнего к внутреннему. В приведенном примере это показано в операторе
ns1::ns2::mi = ns1::f() * ns1::ns2::g();
Ниже приведен текст программы ( Пример 4 ), демонстрирующей сказанное
Пример 4_(6)
5), 6) Применение директивы using в строке описания имени пространства имен позволяет отказаться от необходимости ссылаться на имена пространства имен (ссылаться на квалификаторы) при описании имен переменных, функций, классов, объектов, что значительно сокращает размеры текста программы и упрощает ее понимание. В частности, приведенная выше запись сможет иметь вид
mi = f() * g();
С учетом директивы using описание пространства имен может иметь виды
using namespace ns;
using ns :: name;
Описание using namespace ns; включает имя пространства имен ns и обеспечивает обращение ко всем именам в тексте программы без применения квалификаторов.
Второе описание using ns :: name; выделяет в пространстве имен ns только одно имя в тексте программы ( здесь name), при обращении к которому обходятся без квалификатора.
В тексте программы в главной функции _tmain() показаны три строки, впереди которых расположен текст /*/ 1 */. Эти строки не закомментированы и показывают работу с описанием пространства имен в виде using namespace ns;. Следующие три стоки впереди имеют текст // 2 */ и являются закомментированными. Они демонстрируют работу с описанием using ns::name. Как видно, для перевода не комментированных строк в комментируемые и наоборот следует выполнить /*/ 1*/ -> // * 1/ или // 2 */ -> /*/ 2 */.
Пояснения: f() = fi + fj + fk = 9; g() = gi + gj + gk = 15; mi = 195.
Пример 5 _(7)_(в программе рассматриваются одновременно структуры 5) и 6))
Пространство имен std зарезервировано за стандартной библиотекой. Если стандартную библиотеку не включать в глобальное пространство имен, то в тексте программы придется писать, например, std::cout<< “ ”<<x<<”\n”; std::cin>>x; и так далее. Для ограничения использования глобального пространства можно применить такую структуру программы:
#include <iostream>
using std::cout; // без using namespace std;
using std::cin; // и другое
int main()
{ cout<<” “;
cin>>x;
-- - - -
}
Составить самостоятельно примеры (8) программ с применением различных форм использования using.