246071-Либерти-Освой-самостоятельно-С-за-21-день (852741), страница 87
Текст из файла (страница 87)
После выполнения этогокоданаэкранепоявитсястрока:j=10Комитет по стандартизации не рекомендует использовать statie для ограничения областивидимостивнешнейпеременной,каквследующемпримере:statieintstaticInt=10;intmain(){//...}Если сейчас такое использование static просто не рекомендуется, то в будущем подобноевыражение вообще может рассматриваться как ошибочное. Поэтому уже сейчас вместо staticлучшеиспользоватьпространстваименРекомендуется:Используйтепространстваимен.Не рекомендуется:Не применяйте ключевое слово static для ограничения областивидимостипеременнойпределамифайла.СозданиепространстваименСинтаксис объявления пространства имен аналогичен синтаксису объявления структур иклассов. После ключевого слова namespace стоит имя пространства имен, которое может иотсутствовать, а затем следует открывающая фигурная скобка.
Пространство имен завершаетсязакрывающейфигурнойскобкойбезточкисзапятойвконцевыражения.Например:namespaceWindow{voidmove(intx,intу);}Имя Window идентифицирует пространство имен. Можно создавать множествоэкземпляровименованныхпространствимен,расположенныхвнутриодногофайлаиливразныхединицах трансляции. Примером тому может быть пространство имен std стандартнойбиблиотеки C++. Его использование обосновано в данном случае тем, что стандартнаябиблиотекапредставляетсобойлогическиединуюгруппуфункций.Основное назначение пространств имен состоит в группировании связанных элементов вименованной области программы.
Ниже показан пример пространства имен, объединяющегонесколькофайловзаголовков://header1.hnamespaceWindow{voidmove(intx,intу);}//header2.hnamespaceWindow{voidresize(intx,inlу);}ОбъявлениеиопределениетиповВнутри пространства имен можно объявлять и определять типы и функции. Тут необойтись без обсуждения стратегических подходов программирования в C++. Правильностьструктуры программы определяется тем, насколько четко отделен интерфейс программы от еепроцедурнойчасти.Этомупринципунеобходимоследоватьнетолькоприработесклассами,нои при создании пространств имен.
Ниже показан пример плохо структурированногопространстваимен:namespaceWindow{//...другиеобъявленияиопределенияпеременных.voidmove(intx,intу);//объявленияvoidresize(intx,intу);//...другиеобъявленияиопределенияпеременных.voidmove(intx,intу){if(x<MAX_SCREEN_X&&x>0)if(у<MAX_SCREEN_Y&&у>0)platform.move(x,у);//специальнаяпрограмма}voidresize(intx,intу){if(x<MAX_SIZE__X&&x>0)if(у<MAX_SIZE_Y&&у>0)platform.resize(x,у);//специальнаяпрограмма}//...продолжениеопределений}Наглядно видно, как быстро пространство имен становится хаотичным и беспорядочным!Причем в этом примере объявление пространства имен составляло всего около 20 строк, а вочтопревратиласьбыпрограмма,будьобъявлениеболеедлинным?ОбъявлениефункцийзапределамипространстваименФункции пространства имен следует объявлять за пределами тела пространства.
Этопозволитявноотделитьобъявленияфункцийотопределенияихвыполнения,незахламляятелопространства имен. Кроме того, вынос объявлений функции даст возможность разместитьпространствоимениеговнедренныеобъявлениявфайлезаголовка,аопределениявыполненияпоместитьвисполняемыйфайлпрограммы.Например://файлheader.hnamespaceWindow{voidmove(intx,intу);//другиеобъявления}//fileimpl.cppvoidWindow::move(intx,intу){//кодперемещенияокна}ДобавлениеновыхчленовДобавление новых членов в пространство имен осуществляет только в теле пространства.Невозможно создавать новые члены пространства имен вне тела пространства, указывая егоимя,какэтоделалосьсобъектамиклассов.Компиляторответитнаэтосообщениемобошибке.Примертакойошибкипоказанниже.namespaceWindow{//рядобъявлений}//кодпрограммыintWindow::newIntegerInNamespace;//ошибкаПоследняя строка неправильна, и компилятор сообщит об этом. Чтобы исправить ошибку,перенеситеобъявлениепеременной-членаnewIntegerInNamespaceвтелопространстваимен.Все заключенные в пространстве имени члены являются открытыми.
Поэтомунеправильнымбудетиследующийкод:namespaceWindow{private:voidmove(intx,intу);}ВложенияпространстваименОдно пространство имен можно вложить в другое пространство имен. К подобномувложению прибегают в том случае, когда определение выполнения одного пространства имендолжно содержать объявление нового пространства. Чтобы обратиться к члену внутреннегопространства имен, необходимо явно указать имена обоих пространств.
Так, в следующемпримере одно именованное пространство объявляется внутри другого именованногопространства:namespaceWindow{namespacePane{voidsize(intx,intу);}}Для доступа к функции size() за пределами пространства имен Window нужно дополнитьимя вызываемой функции именами пространств имен, внутри которых она была объявлена,например:intmain(){Window::Pane::size(10,20);return0;}ИспользованиепространстваименТеперь рассмотрим пример использования пространства имен и связанного с нимоператора видимости.
Сначала внутри пространства имен Windowoбъявляютcя все типы ифункции,послечегозаегопределамиследуютопределенияфункций-членов.Чтобыопределитьфункцию, объявленную в пространстве имен, следует перед именем функции установить имяпространстваимениоператорвидимости,какэтоделаетсявлистинге17.1.Листинг17.1.Использованиепространстваимен1:#include<iostream>2:3:namespaceWindow4:{5:constintMAX_X=306:constintMAX_Y=407:classРапе8:{9:public:10:Pane();11:~Pane();12:voidsize(intx,intу)13:voidmove(intx,intу)14:voidshow();15:private:16:staticintcnt;17:intx;18:intу;19:};20:}21:22:intWindow::Pane::cnt=0;23:Window::Pane::Pane():x(0),y(0){}24:Windo::Pane::~Pane(){}25:26:voidWindow;:Pane::size(intx,inty)27:{28:if(x<Window::MAX_X&&x>0)29:Pane;:x=x:30:if(y<Window;;MAX_Y&&y>0)31:Pane::y=y;32:}33:voidWindow;:Pane::move(intx,inty)34:{35:if(x<Window::MAX_X&&x>0)36:Pane::x=x;37:if(y<Window::MAX_Y&&y>0)38:Pane::y=y;39:}40:voidWindow::Pane::show()41:{42:std::cout<<"x"<<Pane::x;43:std::cout<<"y"<<Pane::y<<std::endl;44:}45:46:intmain()47:{48:Window::Panepane;49:50:pane.move(20,20);51:pane.show();52:53:return0;54:}Результат:x20y20Анализ:Обратитевнимание,чтоклассPaneвложенвпространствоименWindow.ПоэтомуприобращениикобъектамклассаPaneихименадополняютсяидентификаторомWindow::.Статическая переменная-член cnt, объявленная в строке 16 внутри класса Pane,определяется как обычно.
Но при определении функции-члена Pane: :size() и обращениях кпеременным-членам MAX_X и MAX_Y в строках 26-32 используется явное указаниепространства имен. Дело в том, что статическая переменная-член определяется внутри классаPane, а определения других функций-членов (это же справедливо для функции Pane::move())происходят как за пределами класса, так и вне тела пространства имен. Без явного указанияпространстваименкомпиляторпокажетсообщениеобошибке.Обратите внимание также на то, что внутри определений функций-членов обращение кобъявленнымпеременным-членамклассапроисходитсявнымуказаниемименикласса:Pane::xи Pane::y. Зачем это делается? Дело в том, что у вас возникли бы проблемы, если функцияPane::move()определяласьбыследующимобразом:voidWindow::Pane::move(intx,intу){if(x<Window::MAX_X&&x>0)x=x;if(у<Window::MAX_Y&&у>0)У=У;Platform::move(x,у);}Ну что, догадались, в чем проблема? Опасность состоит в том, что компилятор в этомвыраженииникакихошибокнезаметит.Источникпроблемызаключаетсяваргументахфункции.Аргументыxиускроютзакрытыепеременные-члены x и у, объявленные в классе Pane, поэтому вместо присвоения значенийаргументов переменным-членам произойдет присвоение этих значений самим себе.
Чтобыисправитьэтуошибку,необходимоявноуказатьпеременные-членыкласса:Pane::x=x;Pane::y=у;КлючевоесловоusingКлючевое слово using может использоваться и как оператор, и в качестве спецификаторапри объявлении членов пространства имен, но синтаксис использования using при этомменяется.ИспользованиеusingкакоператораС помощью ключевого слова using расширяются области видимости всех членовпространства имен. Впоследствии это позволяет ссылаться на члены пространства имен, неуказывая соответствующее имя пространства.
Использование using показано в следующемпримере:namespaceWindow{intvaluo1=20;intvalue2-40;}...Window::value1=10;usingnamespaceWindow;value2=30;Все члены пространства имен Window становятся видимыми, начиная от строки usingnamespace Window; и до конца соответствующего модуля программы. Обратите внимание, чтоесли для обращения к переменной value1 в верхней части фрагмента программы необходимоуказывать пространство имен, то в этом нет необходимости при обращении к переменнойvalue2,посколькуоператорusingсделалвидимымивсечленыпространстваименWindow.Оператор using может использовать в любом модуле программы с различной областьювидимости.
Когда выполнение программы выходит за область видимости данного модуля,автоматическистановятсяневидимымивсечленыпространстваимен,открытыевэтоммодуле.Проанализируйтеэтонаследующемпримере:namespaceWindow{intvalue1=20;intvalue2=40;}//...voidf(){{usingnamespaceWindow;value2=30;}value2=20;//ошибка!}Последняястрокакодафункцииf()—value2=20—вызоветошибкувовремякомпиляции,поскольку переменная value2 в этом месте невидима.