Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование основы языка С++. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
Это интересно! Джон Маккарти (4 сентября 1927, Бостон – 24 октября 2011, Стэнфорд) – американский информатик, автор термина «искусственный интел­лект» (1955), изобретатель языка Лисп (1958), осно­воположник функционального программирования, лау­реат премии Тьюринга (1971) за огромный вклад в об­ласть исследований искусственного интеллекта. Член
Национальной академии наук США (1989). У Маккарти рано проявились склонности к математике, в юности он самостоятельно изучал ее по университетским учебникам, которые использовались в расположенном не­подалеку Калифорнийском технологическом институте. В результате, поступив в университет, он смог сразу пропустить два первых года по математике. В 1948 году получил степень бакалавра математики в Калифорнийском технологическом институте и степень Ph.D. по математике в Принстоне в 1951 году. После кра­тковременных должностей в Принстонском и Стэнфордском университетах, Дартмутском колледже и Массачусетском технологическом институте, он стал профессором в Стэнфорде в 1962 году, где он и оставался до своего ухода на пенсию в конце 2000-го. Маккарти отстаивал использование математической логики для искусственного интеллекта. В 1958 году он предложил систему «принятия сове­тов», которая позже вдохновила работы по ответам на запросы и логическому программированию. В том же году он изобрел язык программирования Лисп и опу­бликовал его описание в журнале Communications of the ACM в апреле 1960 г. В 1961 году Джон Маккарти публично предположил, что компьютерная технология раз­деления времени может привести к будущему, в котором компьютерная мощь и даже определенные приложения могут продаваться с использованием бизнес-мо­дели сферы услуг (подобно воде или электричеству). Эта идея компьютерных или информационных услуг была очень популярна в конце 1960 годов, но вышла из моды к середине 1970 годов, так как стало ясно, что аппаратные, программные и ком­муникационные технологии того времени были просто еще не готовы к этому. Тем не менее, начиная с 2000 года, эта идея вновь объявилась, всплыв на поверхность в новых формах.
Особенности. Основной особенностью функционального програм­мирования, определяющей как преимущества, так и недостатки данной парадигмы, является то, что в ней реализуется модель вычислений без состояний. Если императивная программа на любом этапе исполнения имеет состояние, то есть совокупность значений всех переменных, и производит побочные эффекты, то чисто функциональная программа ни целиком, ни частями состояния не имеет и побочных эффектов не про-
21
изводит. То, что в императивных языках делается путем присваивания значений переменным, в функциональных достигается путем передачи выражений в параметры функций. Непосредственным следствием ста­новится то, что чисто функциональная программа не может изменять уже имеющиеся у нее данные, а может лишь порождать новые путем копирования и/или расширения старых. Следствием того же является отказ от циклов в пользу рекурсии.
Достоинства функциональной парадигмы программирования
1. Повышение надежности кода – повышение надежности кода за счет четкой структуризации и отсутствия необходимости отслеживания побочных эффектов. Любая функция работает только с локальными дан­ными и работает с ними всегда одинаково, независимо от того, где, как и при каких обстоятельствах она вызывается. Невозможность мутации данных при пользовании ими в разных местах программы исключа­ет появление трудно обнаруживаемых ошибок (таких, например, как случайное присваивание неверного значения глобальной переменной в императивной программе).
2. Удобство организации модульного тестирования – поскольку функция в функциональном программировании не может порождать побочные эффекты, менять объекты нельзя как внутри области види­мости, так и снаружи (в отличие от императивных программ, где одна функция может установить какую-нибудь внешнюю переменную, счи­тываемую второй функцией). Единственным эффектом от вычисления функции является возвращаемый ей результат, и единственный фактор, оказывающий влияние на результат – это значения аргументов. Таким образом, имеется возможность протестировать каждую функцию в про­грамме, просто вычислив ее от различных наборов значений аргументов. При этом можно не беспокоиться ни о вызове функций в правильном порядке, ни о правильном формировании внешнего состояния. Если любая функция в программе проходит модульные тесты, то можно быть уверенным в качестве всей программы. В императивных программах проверка возвращаемого значения функции недостаточна: функция может модифицировать внешнее состояние, которое тоже нужно про­верять, чего не нужно делать в функциональных программах.
3. Возможности оптимизации при компиляции – позволяет описы­вать программу в так называемом «декларативном» виде, когда жесткая последовательность выполнения многих операций, необходимых для вычисления результата, в явном виде не задается, а формируется авто-
22
матически в процессе вычисления функций. Это обстоятельство, а также отсутствие состояний дает возможность применять к функциональным программам достаточно сложные методы автоматической оптимизации.
4. Возможности параллелизма – программы на функциональном языке предоставляют широчайшие возможности для автоматическо­го распараллеливания вычислений. Поскольку отсутствие побочных эффектов гарантировано, в любом вызове функции всегда допустимо параллельное вычисление двух различных параметров – порядок их вычисления не может оказать влияния на результат вызова.
Недостатки функциональной парадигмы программирования
Недостатки функционального программирования вытекают из тех же самых его особенностей. Отсутствие присваиваний и замена их на порождение новых данных приводят к необходимости постоянного вы­деления и автоматического освобождения памяти, поэтому в системе исполнения функциональной программы обязательным компонентом становится высокоэффективный сборщик мусора. Нестрогая модель вы­числений приводит к непредсказуемому порядку вызова функций, что создает проблемы при вводе-выводе, где порядок выполнения операций важен. Кроме того, очевидно, функции ввода в своем естественном виде (например, getchar из стандартной библиотеки языка C) не являются чи­стыми, поскольку способны возвращать различные значения для одних и тех же аргументов, и для устранения этого требуются определенные ухищрения. Для преодоления недостатков функциональных программ уже первые языки функционального программирования включали не только чисто функциональные средства, но и механизмы императивного программирования (присваивание, цикл, «неявный PROGN» были уже в Лиспе). Использование таких средств позволяет решить некоторые практические проблемы, но означает отход от идей (и преимуществ) функционального программирования и написание императивных про­грамм на функциональных языках. В чистых функциональных языках эти проблемы решаются другими средствами, например, в языке Haskell ввод-вывод реализован при помощи монад – нетривиальной концеп­ции, позаимствованной из теории категорий.
23
РАЗДЕЛ 2 ИСТОРИЯ ПОЯВЛЕНИЯ ЯЗЫКА ПРОГРАММИРОВАНИЯ С++
C++ – компилируемый, статически типизированный язык про­граммирования общего назначения. Поддерживает такие парадигмы программирования как процедурное программирование, объектно­ориентированное программирование, обобщенное программирование, обеспечивает модульность, раздельную компиляцию, обработку ис­ключений, абстракцию данных, объявление типов (классов) объектов, виртуальные функции. Стандартная библиотека включает, в том числе, общеупотребительные контейнеры и алгоритмы. C++ сочетает свойства как высокоуровневых, так и низкоуровневых языков. В сравнении с его предшественником – языком C, – наибольшее внимание уделено под­держке объектно-ориентированного и обобщенного программирования. C++ широко используется для разработки программного обеспече­ния, являясь одним из самых популярных языков программирования. Область его применения включает создание операционных систем, раз­нообразных прикладных программ, драйверов устройств, приложений для встраиваемых систем, высокопроизводительных серверов, а также развлекательных приложений. Существует множество реализаций языка C++, как бесплатных, так и коммерческих и для различных платформ.
Язык программирования С++ был создан в начале 1980-х годов, его создатель сотрудник фирмы Bell Laboratories – Бьерн Страуструп. Он придумал ряд усовершенствований к языку программирования C, для собственных нужд. Т. е. изначально не планировалось создания языка программирования С++. Ранние версии языка С++, известные под именем «Cи с классами», начали появляться с 1980 года. Язык C, будучи базовым языком системы UNIX, на которой работали компью­теры фирмы Bell, является быстрым, многофункциональным и пере­носимым. Страуструп добавил к нему возможность работы с классами и объектами, тем самым зародил предпосылки нового, основанного на синтаксисе С, языка программирования. Синтаксис C++ был основан на синтаксисе C, так как Бьерн Страуструп стремился сохранить со­вместимость с языком C.
Развитие. Первое издание «Языка программирования C++» вышло в 1985 году. Обеспечивает первое описание этого языка, что было важно
24
из-за отсутствия официального стандарта. В 1989 году вышла версия 2.0 языка C++. Его новые возможности включали множественное наследо­вание, абстрактные классы, статические функции-члены, функции-кон­станты и защищенные члены. В 1990 году вышло «Комментированное справочное руководство по C++», положенное впоследствии в основу стандарта. Последние обновления включали шаблоны, исключения, пространства имен, новые способы приведения типов и логический тип. В 1998 году был опубликован стандарт языка ISO/IEC 14882:1998 (известный как C++98), разработанный комитетом по стандартизации C++ (ISO/IEC JTC1/SC22/WG21 working group). Стандарт состоит из двух частей – основы языка (core language) и стандартной библиотеки языка, которая включает Standard Template Library (STL) и модифици­рованный вариант стандартной библиотеки языка C. В 2003 году был опубликован стандарт языка ISO/IEC 14882:2003, где были исправлены выявленные ошибки и недочеты предыдущей версии стандарта. В 2005 году был выпущен отчет Library Technical Report 1. Отчет описывает расширения стандартной библиотеки, которые, должны быть вклю­чены в следующую версию языка C++. С 2009 года велась работа по обновлению предыдущего стандарта, предварительной версией нового стандарта сперва был C++09, а спустя год C++0x, сегодня – C++11, куда были включены дополнения в ядро языка и расширение стандартной библиотеки.
Название. Название C++ придумал Рик Масситти. Название ука­зывает на эволюционную природу перехода к нему от C. "++" – это операция приращения в C. Чуть более короткое имя C+ является син­таксической ошибкой; кроме того, оно уже было использовано как имя совсем другого языка. Знатоки семантики C находят, что C++ хуже, чем ++C. Названия D язык не получил, поскольку он является расширением C и в нем не делается попыток исцеляться от проблем путем выбрасы­вания различных особенностей.
Объектно-ориентированные особенности. C++ добавляет к C объ­ектно-ориентированные возможности. Он вводит классы, которые обеспечивают три самых важных свойства ООП: инкапсуляцию, на­следование и полиморфизм. Методы класса – это функции, которые смогут применяться к экземплярам класса, то есть метод – это функция объявленная внутри класса и предназначенная для работы с его объек­тами. Методы объявляются в теле класса. Описываться могут там же, но могут и за пределами класса (внутри класса в таком случае достаточно
25
представить прототип метода, а за пределами класса определять метод поставив перед его именем – имя класса и оператор ::). Методы и поля входящие в состав класса называются членами класса. При этом методы часто называют функциями-членами класса.
Наследование. В C++ при наследовании одного класса от другого наследуется реализация класса, плюс класс-наследник может добавлять свои поля и функции или переопределять функции базового класса. Множественное наследование разрешено. Конструктор наследника вызывает конструкторы базовых классов, а затем конструкторы нестати­ческих членов-данных, являющихся экземплярами классов. Деструктор работает в обратном порядке. Наследование бывает публичным, защи­щенным и закрытым.
Полиморфизм. Целью полиморфизма, применительно к объек­тно-ориентированному программированию, является использование одного имени для задания общих для класса действий. Выполнение каждого конкретного действия будет определяться типом данных. Преимуществом полиморфизма является то, что он помогает снижать сложность программ, разрешая использование того же интерфейса для задания единого класса действий. Выбор же конкретного действия, в зависимости от ситуации, возлагается на компилятор. Полиморфизм может применяться также и к операторам.
Инкапсуляция. Основным способом организации информации в C++ являются классы. В отличие от структуры (struct) языка C, кото­рая может состоять только из полей и вложенных типов, класс (class) C++ может состоять из полей, вложенных типов и функций-членов. Инкапсуляция в С++ реализуется через указание уровня доступа к чле­нам класса: они бывают публичными (public), защищенными (protected) и закрытыми (private). В C++ структуры отличаются от классов тем, что по умолчанию члены и базовые классы у структуры публичные, а у класса – собственные.
Стандартная библиотека. В языке программирования C++ термин Стандартная Библиотека означает коллекцию классов и функций, на­писанных на базовом языке. Стандартная Библиотека поддерживает не­сколько основных контейнеров, функций для работы с этими контейне­рами, объектов-функции, основных типов строк и потоков (включая ин­терактивный и файловый ввод-вывод), поддержку некоторых языковых особенностей, и часто используемые функции для выполнения таких за­дач, как, например, нахождение квадратного корня числа. Стандартная
26
Библиотека языка C++ также включает в себя спецификации стандарта ISO C90 стандартной библиотеки языка Си. Функциональные осо­бенности Стандартной Библиотеки объявляются внутри пространства имен std. Стандартная библиотека шаблонов (STL) – подмножество стандартной библиотеки C++ и содержит контейнеры, алгоритмы, итераторы, объекты-функции и т. д. Заголовочные файлы стандартной библиотеки C++ не имеют расширения «.h». Стандартная библиотека C++ содержит последние расширения C++ стандарта ANSI (включая библиотеку стандартных шаблонов и новую библиотеку iostream). Она представляет собой набор файлов заголовков. Отличия С++ от С по­казаны на рисунке 2.1.
Рисунок 2.1 – Основные отличия языка С++ от С
В С++ не разрешается:
вызывать функцию main() внутри программы, в то время как в C
•
это действие правомерно;
неявное приведение типов между несвязанными типами указателей;
•
использовать функции, которые еще не объявлены.
•
Достоинства и недостатки. С++ – язык, складывающийся эволюци-
онно. Каждый элемент С++ заимствовался из других языков отдельно и независимо от остальных элементов (ничто из предложенного С++ за всю историю его развития не было новшеством в Computer Science), что сделало язык чрезвычайно сложным, со множеством дублирующихся и
27
взаимно противоречивых элементов, блоки которых основаны на раз­ных формальных базах. Критики С++ не противопоставляют ему какой­либо конкретный язык, а наоборот, утверждают, что для всякого случая применения С++ всегда существует альтернативный инструментарий, позволяющий решить ту же задачу более эффективно и качественно. В свою очередь, сторонники С++ считают некорректным сравнивать различные аспекты С++ с совершенно различными языками, так как общий набор средств и возможностей С++ существенно шире, чем в большинстве языков, с которыми проводится сравнение, и сама по себе широта возможностей, на их взгляд, является веским оправданием не­совершенства каждой отдельно взятой возможности. Более того, по их мнению, высокая совместимость с Си является одной из принципиаль­ных черт языка, и потому все недостатки С++ оправданы преимущества­ми, предоставляемыми этой совместимостью. Основные достоинства и недостатки приведены в таблице 2.1.
Таблица 2.1 – основные достоинства и недостатки С++
Достоинства Недостатки
Высокая совместимость с языком Си Вычислительная производительность Поддержка различных стилей програм­мирования структурное объектно-ориентированное обобщенное программирование функциональное программирование порождающее метапрограммирование Автоматический вызов деструкторов объектов упрощает и повышает надеж­ность управления памятью и другими ресурсами Перегрузка операторов Шаблоны Возможность расширения языка для поддержки парадигм, которые не под­держиваются компиляторами напря­мую Доступность
Плохо продуманный синтаксис сужа­ет спектр применимости языка Язык не содержит многих важных возможностей Язык содержит опасные возмож­ности Производительность труда програм­мистов на языке оказывается не­оправданно низка Громоздкость синтаксиса Тяжелое наследие Необходимость следить за памятью
28
РАЗДЕЛ 3 БАЗОВЫЕ ПОНЯТИЯ С++
Любая программа должно отвечать следующим критериям качества:
корректность – программа должна работать правильно;
•
надежность – программа не должна «зависать» или «зацикливаться»
•
при любых исходных данных;
эффективность – программа должна использовать, по возможности,
•
минимальное количество ресурсов, как по памяти, так и по времени;
эргономичность – удобство для пользователя;
•
читабельность – удобство для программиста;
•
переносимость – программа должна работать на любых устройствах.
•
3.1 Состав языка
В тексте на любом естественном языке можно выделить четыре основных элемента: символы, слова, словосочетания и предложения. Подобные элементы содержит и алгоритмический язык, только слова называют лексемами (элементарными конструкциями), словосочета­ния – выражениями, а предложения – операторами. Лексемы образу­ются из символов, выражения – из лексем и символов, а операторы – из символов, выражений и лексем:
алфавит языка, или его символы – это основные неделимые знаки,
•
с помощью которых пишутся все тексты на языке;
лексема, или элементарная конструкция, – минимальная единица
•
языка, имеющая самостоятельный смысл;
выражение задает правило вычисления некоторого значения;
•
оператор задает законченное описание некоторого действия.
•
3.2 Структура программы на С++
Программа на языке С/С++ состоит из:
Директив препроцессора
•
Описаний
•
Функций
•
Главная функция носит имя main и должна быть обязательно. Общую структуру программы на языке С/С++ можно представить следующим
29
образом:
директивы препроцессора //1 описание глобальных переменных //2
тип_результата main (параметры) //3
{ тело главной функции }
тип_результата F1 (параметры 1) { тело функции F1; }
тип_результата F2 (параметры 2) { тело функции F2; }
тип_результата FN (параметры N) { тело функции FN; }
Директивы препроцессора – определяют действия по преобразова­нию программы перед компиляцией, а также включают инструкции, которым компилятор следует во время компиляции;
Объявления – описания переменных, функций, структур, классов и типов данных;
Описание функций, выполняемых в проекте. В языке С++ существу­ет только один вид подпрограмм – подпрограмма-функция. Функция состоит из заголовка и тела функции. Заголовок состоит из: типа ре-
зультата, возвращаемого функцией; имени функции; списка параметров, необходимых для выполнения функции. Тело функции заключается в опера-
торные скобки {}, и содержит описание локальных данных и операторы функции:
тип_результата имя_функции (параметры)
{
описание данных;
оператор1;
оператор2;
30
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]