246071-Либерти-Освой-самостоятельно-С-за-21-день (852741), страница 86
Текст из файла (страница 86)
Не приступайте к изучению материаласледующей главы, если для вас остались неясными хотя бы некоторые из предложенных нижевопросов.Контрольныевопросы1.Чтотакоеоператорвводаикаконработает?2.Чтотакоеоператорвыводаикаконработает?3. Перечислите три варианта перегруженной функции cin.get() и укажите основные ихотличия.4.Чемcin.read()отличаетсяотcin.getline()?5. Какая ширина устанавливается по умолчанию для вывода длинных целых чисел спомощьюоператоравывода?6.Какоезначениевозвращаетоператорвывода?7.Какойпараметрпринимаетсяконструкторомобъектаofstream?8.Чтоустанавливаетаргументios::ate?Упражнения1.Напишитепрограмму,использующуючетырестандартныхобъектаклассаiostream—cin,cout,cerrиclog.2.
Напишите программу, предлагающую пользователю ввести свое полное имя споследующимвыводомэтогоименинаэкран.3.Перепишителистинг16.9,отказавшисьотиспользованияметодовputback()иignore().4.Напишитепрограмму,считывающуюимяфайлавкачествеаргументакоманднойстрокииоткрывающую файл для чтения. Разработайте алгоритм анализа всех символов, хранящихся вфайле, и выведите на экран только текстовые символы и знаки препинания (пропускайте всенепечатаемыесимволы).Закройтефайлпередзавершениемработыпрограммы.5. Напишите программу, которая выведет заданные аргументы командной строки вобратномпорядке,отбросивимяпрограммы.День17-й.ПространстваименОдним из дополнений стандарта ANSI C++ является возможность использованияпрограммистами пространств имен, позволяющих избежать конфликтов имен при работе сбольшимколичествомбиблиотек.Сегоднявыузнаете:•Какиефункциииклассывызываютсяпоимени•Каксоздаютсяпространстваимен•Какиспользуютсяпространстваимен•КакиспользуетсястандартноепространствоименstdВведениеКонфликтыименвозникаютиз-занедомолвокмеждуразработчикамиСиC++.СтандартыANSI предлагают способ решения этой проблемы с помощью пространств имен (namespaces).Однако следует проявлять осторожность, так как не все компиляторы поддерживают этосредство.Конфликтименвозникаетвтехслучаях,когдавдвухчастяхпрограммынаходятсяподобныеименассовпадающимиобластямивидимости.Наиболеечастоэтослучаетсяприиспользованииразличных пакетов библиотек.
Например, в разных библиотеках классов контейнеров частообъявляетсяииспользуетсяклассList.(Болееподробноклассыконтейнероврассматриваютсяназанятии19ч)Тот же класс List используется и в библиотеках окон. Предположим, необходимореализовать набор окон для приложения и применить класс List из библиотеки классовконтейнеров. Для этого объявляется экземпляр класса List из библиотеки окон, чтобыподдержать работу окон приложения. Однако в результате может оказаться, что его функциичлены недоступны, поскольку компилятор автоматически связал объявленный класс саналогичнымклассомListизстандартнойбиблиотекиклассовконтейнеров,которыйвамвовсенебылнужен.'Пространство имени используется для разделения глобальных пространств имен, чтобыисключитьили,покрайнеймере,уменьшитьколичествоконфликтовимен.Пространстваименвесьмапохожинаклассы,втомчислеисинтаксисом.Объявленныевнутрипространстваимениэлементыпринадлежаткэтомупространству,ноявляютсяоткрытыми.Пространстваименмогутвзаимноперекрываться.Соответственноифункциимогутобъявлятьсякаквнутри,такизапределамипространствимен.Впоследнемслучаепривызоветакойфункцииследуетявноуказыватьсоответствующеепространствоимен.ВызовпоименифункцийиклассовВ процессе анализа кода программы и создания списка имен функций и переменныхкомпилятор проверяет программу на наличие конфликтов имен.
Конфликты, которые самкомпиляторрешитьневсостоянии,могутустранятьсякомпоновщиком.Компиляторневсостояниипроверитьконфликтыименвединицахтрансляции(например,файлах объектов). Эта задача решается компоновщиком приложений. Поэтому компилятор непокажетдажепредупреждение.Довольно часто компоновщик выдает сообщение об ошибке Identifier multiply defined(множественное объявление идентификатора). Это сообщение появится в том случае, если выпопытаетесьописатьидентификаторысодинаковымиименамииперекрывающимисяобластямивидимости.Еслидваидентификаторабудутобъявленысобщимиобластямивидимостиводномфайле источника, то об ошибке сообщит компилятор.
Сообщение об ошибке поступит откомпоновщикаприпопыткескомпилироватьисвязатьследующийкодпрограммы://файлfirst.сppintintegerValue=0;intmain(){intintegerValue-0;//...return0;};//файлsecond.cppintintegerValue=0;//конецsecond.cppКомпоновщик выдает сообщение in second.obj: integerValue already defined in first.obj(integerValue из second.obj уже объявлен в first.obj). Если бы эти имена располагались в разныхобластяхвидимости,токомпиляторикомпоновщикнеимелибыничегопротив.Можетпоступитьитакоепредупреждениеоткомпилятора:identifierhiding(идентификаторскрыт). Суть его состоит в том, что в файле first.cpp объявление переменной integerValue вфункцииmain()скрываетглобальнуюпеременнуюстакимжеименем.Чтобы использовать в функции main() глобальную переменную integerVaalue, объявленнуюза пределами main(), необходимо явно указать глобальность этой переменной с помощьюоператора видимости (::).
Так, в следующем примере значение 10 будет присвоено глобальнойпеременнойintegerValue,анепеременнойстакимжеименем,объявленнойвнутриmain()://файлfirst.cppintintegerValue=0;intmain(){intintegerValue=0;::integerValue=10;//присваиваемглобальнойпеременнойintegerValue//...return0;};//файлsecond.cppintintegerValue=0;//конецsecond.cppПримечание:Обратите внимание на использование оператора видимости (: ), которыйнеобходим для указания глобальности переменной integerValue в том случае, если в функциибылаобъявленапеременнаястакимжеименем.Проблема с двумя глобальными переменными, объявленными за пределами какой-либофункции, заключается в том, что они имеют одинаковые имена и перекрывающиеся областивидимостииэтовызываетошибкувработекомпоновщика.Новыйтермин:Подвидимостьюобъекта,которыйможетбытьпеременной,классомилифункцией, понимают ту часть программы, в которой данный объект может использоваться.Например, переменная, объявленная и определенная за пределами всякой функции, имеетфайловую, или глобальную область видимости.
Ее видимость распространяется от точкиобъявления до конца файла. Переменная, имеющая модульную, или локальную областьвидимости, объявляется внутри программного модуля. Чаще всего локальные переменныеобъявляются в теле функции. Ниже показаны примеры объектов с различными областямивидимости:intglobaiScopeInt=5;voidf(){intlocalScopeInt=10;}intmain(){intlocalScopeInt=15;{intanotherLocal=20;intlocalScopeInt=30;}return0;}ПерваяцелочисленнаяпеременнаяGlobalScopeIntбудетвиднакаквнутрифункцииf(),такиmain(). В теле функции f() содержится объявление переменной localScopeInt. Ее областьвидимостилокальна,т.е.ограничиваетсяпределамимодуля,содержащегообъявлениефункции.Функция main() не может получить доступ к переменной localScopeInt функции f(). Кактолько завершается выполнение функции f(), переменная localScopeInt удаляется из памятикомпьютера.
Объявление третьей переменной, также названной localScopeInt, располагается втелефункцииmain().Областьеевидимоститакжелокальна.Обратите внимание: переменная localScopeInt функции main() не конфликтует содноименнойпеременнойфункцииf().Видимостьследующихдвухпеременных—anotherLocalиlocalScopeInt—такжеограниченаобластьюмодуля.Другимисловами,этипеременныевидныотместаобъявлениядозакрывающейфигурнойскобки,ограничивающейтеломодуля,вкоторомэтафункциябылаобъявлена.Вы, наверное, обратили внимание, что в программе объявляются две одноименныелокальные переменные localScopeInt, причем одна из них объявляется во внешнем модуле, авторая — во вложенном.
Таким образом, их области видимости перекрываются. Переменная,объявленнаявовнутреннеммодуле,будетскрыватьвнемпеременнуювнешнегомодуля.Послезакрытия фигурной скобки внутреннего модуля вторая переменная localScopeInt из внешнегомодуля вновь становится видимой. Все изменения, внесенные в localScopeInt внутри фигурныхскобок,никоимобразомнеповлияютназначениевнешнейпеременнойlocalScopeInt.Новый термин:Имена могут иметь внутреннюю или внешнюю связь. Оба эти терминаотносятся к использованию или доступности имени в нескольких или одной программнойединице. На всякое имеющее внешнюю связь имя можно ссылать только в пределахопределяющей его единицы.
Например, переменная, имеющая внутреннюю связь, можетиспользоваться функциями только внутри блока программы, где эта переменная былаобъявлена. Имена с внешними связями доступны функциям из других блоков. Примерывнутреннихивнешнихсвязейиллюстрируетприведенныйнижекод.//файл:first.cppintexternalInt=5;constintj=10;intmain(){return0;}//файл:second.cppexternintexternalInt;intanExternalInt=10;constintj=10;ПеременнаяexternalInt,объявленнаявфайлеfirst.cpp,имеетвнешнююсвязь.Несмотрянаточто она объявлена в файле first.cpp, доступ к этой переменной можно получить и из файлаsecond.cpp. В обоих файлах также есть константы j, которые по умолчанию имеют внутренниесвязи. Чтобы изменить заданную по умолчанию внутреннюю связь констант, необходимо явноуказатьихглобальность,какэтосделановследующемпримере://файл:first.cppexternconstintj=10;//файл:second.cppexternconstintj;#include<iostrean>intmain(){std::cout<<"j="<<j<<std::endl;return0;}Обратитевниманиенаиспользованиеобозначенияпространстваимениstdпередoout,чтопозволяет ссылаться на все объекты етандартний библиотеки ANSI.