Архив опросов
Ваш пол?
У вас за окном сейчас:
я люблю:
Я:

МЕТА - Украина. Рейтинг сайтов Webalta Уровень доверия



Союз образовательных сайтов
Главная / Учебники / Учебники на русском языке / Компьютерные науки / C++


Компьютерные науки - Учебники на русском языке - Скачать бесплатно


М. Хилл, Б. Страустрап
C++



Предисловие

Язык формирует наш способ мышления
и определяет, о чем мы можем мыслить.
- Б.Л. Ворф

С++ - это универсальный язык программирования, задуман-
ный так, чтобы сделать программирование более приятным для
серьезного программиста. За исключением второстепенных дета-
лей С++ является надмножеством языка программирования C. По-
мимо возможностей, которые дает C, С++ предоставляет гибкие и
эффективные средства определения новых типов. Используя опре-
деления новых типов, точно отвечающих концепциям приложения,
программист может разделять разрабатываемую программу на лег-
ко поддающиеся контролю части. Такой метод построения прог-
рамм часто называют абстракцией данных. Информация о типах
содержится в некоторых объектах типов, определенных пользова-
телем. Такие объекты просты и надежны в использовании в тех
ситуациях, когда их тип нельзя установить на стадии компиля-
ции. Программирование с применением таких объектов часто на-
зывают объектно-ориентированным. При правильном использовании
этот метод дает более короткие, проще понимаемые и легче
контролируемые программы.

Ключевым понятием С++ является класс. Класс - это тип,
определяемый пользователем. Классы обеспечивают сокрытие дан-
ных, гарантированную инициализацию данных, неявное преобразо-
вание типов для типов, определенных пользователем, динамичес-
кое задание типа, контролируемое пользователем управление
памятью и механизмы перегрузки операций. С++ предоставляет
гораздо лучшие, чем в C, средства выражения модульности прог-
раммы и проверки типов. В языке есть также усовершенствова-
ния, не связанные непосредственно с классами, включающие в
себя символические константы, inline-подстановку функций, па-
раметры функции по умолчанию, перегруженные имена функций,
операции управления свободной памятью и ссылочный тип. В С++
сохранены возможности языка C по работе с основными объектами
аппаратного обеспечения (биты, байты, слова, адреса и т.п.).
Это позволяет весьма эффективно реализовывать типы, определя-
емые пользователем.

С++ и его стандартные библиотеки спроектированы так,
чтобы обеспечивать переносимость. Имеющаяся на текущий момент
реализация языка будет идти в большинстве систем, поддержива-
ющих C. Из С++ программ можно использовать C библиотеки, и с
С++ можно использовать большую часть инструментальных
средств, поддерживающих программирование на C.

Эта книга предназначена главным образом для того, чтобы
помочь серьезным программистам изучить язык и применять его в
нетривиальных проектах. В ней дано полное описание С++, много
примеров и еще больше фрагментов программ.

Благодарности

С++ никогда бы не созрел без постоянного использования,
предложений и конструктивной критики со стороны многих друзей
и коллег. Том Карджилл, Джим Коплин, Сту Фельдман, Сэнди Фре-
зер, Стив Джонсон, Брайэн Керниган, Барт Локанти, Дуг МакИл-
рой, Дэннис Риччи, Лэрри Рослер, Джерри Шварц и Джон Шопиро
подали важные для развития языка идеи. Дэйв Пресотто написал
текущую реализацию библиотеки потоков ввода/вывода.

Кроме того, в развитие С++ внесли свой вклад сотни лю-
дей, которые присылали мне предложения по усовершенствованию,
описания трудностей, с которыми они сталкивались, и ошибки
компилятора. Здесь я могу упомянуть лишь немногих из них: Гэ-
ри Бишоп, Эндрю Хьюм, Том Карцес, Виктор Миленкович, Роб Мюр-
рэй, Леони Росс, Брайэн Шмальт и Гарри Уокер.


- 2 -

В издании этой книги мне помогли многие люди, в частнос-
ти, Джон Бентли, Лаура Ивс, Брайэн Керниган, Тэд Ковальски,
Стив Махани, Джон Шопиро и участники семинара по С++, который
проводился в Bell Labs, Колумбия, Огайо, 26-27 июня 1985 го-
да.

Мюррэй Хилл, Нью Джерси Бьярн Страустрап









Заметки для Читателя

"О многом," - молвил Морж, - "Пришла
пора поговорить."
- Л. Кэррол

В этой главе содержится обзор книги, список библиографи-
ческих ссылок и некоторые замечания по С++ вспомогательного
характера. Замечания касаются истории С++, идей, оказавших
влияние на разработку С++, и мыслей по поводу программирова-
ния на С++. Эта глава не является введением: замечания не
обязательны для понимания последующих глав, и некоторые из
них предполагают знание С++.

Структура Этой Книги

Глава 1 - это короткое турне по основным особенностям С+
+, предназначенное для того, чтобы дать читателю почувство-
вать язык. Программисты на C первую половину главы могут про-
читать очень быстро, она охватывает главным образом черты,
общие для C и С++. Во второй главе описаны средства определе-
ния новых типов в С++, начинающие могут отложить более под-
робное изучение этого до того, как прочтут Главы 2, 3 и 4.

В Главах 2, 3 и 4 описываются средства С++, не входящие
в определение новых типов: основные типы, выражения и струк-
туры управления в С++ программах. Другими словами, в них опи-
сывается подмножество С++, которое по существу является язы-
ком C. Рассмотрение в них проводится гораздо подробнее, но
полную информацию можно найти только в справочном руководс-
тве.

В Главах 5, 6 и 7 описываются средства С++ по описанию
новых типов, особенности языка, не имеющие эквивалента в C. В
Главе 5 приводится понятие базового класса, и показывается,
как можно инициализировать объекты типа, определяемого поль-
зователем, обращаться к ним и, наконец, убирать их. В Главе 6
объясняется, как для определяемого пользователем типа опреде-
лять унарные и бинарные операции, как задавать преобразования
между типами, определяемыми пользователем, и как как задавать
то, каким образом должно обрабатываться каждое создание,
уничтожение и копирование значения определяемого пользовате-
лем типа. Глава 7 описывает концепцию производных классов,
которая позволяет программисту строить более сложные классы
из более простых, обеспечивать альтернативные интерфейсы
класса и работать с объектами эффективно и с гарантией типа в
тех ситуациях, когда типы объектов не могут быть известны на
стадии компиляции.



- 3 -
В Главе 8 представлены классы ostream и istream, предос-
тавляемые стандартной библиотекой для осуществления ввода-вы-
вода. Эта глава имеет двоякую цель: в ней представлены полез-
ные средства, что одновременно является реальным примером
использования С++.

И, наконец, в книгу включено справочное руководство по С++.

Ссылки на различные части этой книги даются в форме
#2.3.4 (Глава 2 подраздел 3.4). Глава с - это справочное ру-
ководство например #с.8.5.5.

Замечания по Реализации

Во время написания этой книги все реализации С++ исполь-
зовали версии единственного интерфейсного компилятора*. Он
используется на многих архитектурах, включая действующие вер-
сии системы операционной системы UNIX на AT&T 3B, DEC VAX,
IBM 370 и Motorolla 68000. Фрагменты программ, которые приво-
дятся в этой книге, взяты непосредственно из исходных файлов,
которые компилировались на 3B в UNIX System V версии 2 [15],
VAX11/750 под 8-ой Редакцией UNIX [16] и CCI Power 6/32 под
BSD4.2 UNIX [17]. Язык, описанный в этой книге, - это "чистый
С++", но имеющиеся на текущий момент компиляторы реализуют
большое число "анахронизмов" (описанных в #с.15.3), которые
должны способствовать переходу от C к С++.

--------------------
* С++ можно купить в AT&T, Software Sales and Marketing,
PO Box 25000, Greensboro, NC 27420, USA (телефон
800-828-UNIX) или в ваших местных организациях, осуществляю-
щих продажу Системы UNIX. (прим. автора)

Упражнения

Упражнения находятся в конце глав. Все упражнения глав-
ным образом типа напишите-программу. Для решения всегда пиши-
те такую программу, которая будет компилироваться и работать
по меньшей мере на нескольких тестовых случаях. Упражнения
различаются в основном по сложности, поэтому они помечены
оценкой степени сложности. Шкала экспоненциальная, так что
если на упражнение (*1) вам потребовалось пять минут, то на
упражнение (*2) вам может потребоваться час, а на (*3) -
день. Время, которое требуется на то, чтобы написать и оттес-
тировать программу, зависит больше от опыта читателя, нежели
от самого упражнения. Упражнение (*1) может отнять день, если
для того, чтобы запустить ее, читателю сначала придется зна-
комиться с новой вычислительной системой. С другой стороны,
тот, у кого под рукой окажется нужный набор программ, может
сделать упражнение (*5) за час. В качестве источника упражне-
ний к Главам 2-4 можно использовать любую книгу по C. У Ахо и
др. [1] приведено большое количество общих структур данных и
алгоритмов в терминах абстрактных типов данных. Эту книгу
также может служить источником упражнений к Главам 5-7. Одна-
ко языку, который в этой книге использовался, недостает как
функций членов, так и производных классов. Поэтому определяе-
мые пользователем типы часто можно выражать в С++ более эле-
гантно.

Замечания по Проекту Языка

Существенным критерием при разработке языка была просто-
та. Там, где возникал выбор между упрощением руководства по
языку и другой документации и упрощением компилятора, выбира-
лось первое. Огромное значение также предавалось совместимос-
ти с C, это помешало удалить синтаксис C.



- 4 -
В С++ нет типов данных высокого уровня и нет первичных
операций высокого уровня. В нем нет, например, матричного ти-
па с операцией обращения или типа строка с операцией конкате-
нации. Если пользователю понадобятся подобные типы, их можно
определить в самом языке. По сути дела, основное, чем занима-
ется программирование на С++ - это определение универсальных
и специально-прикладных типов. Хорошо разработанный тип, оп-
ределяемый пользователем, отличается от встроенного типа
только способом определения, но не способом использования.

Исключались те черты, которые могли бы повлечь дополни-
тельные расходы памяти или времени выполнения. Например, мыс-
ли о том, чтобы сделать необходимым хранение в каждом объекте
"хозяйственной" информации, были отвергнуты. Если пользова-
тель описывает структуру, состоящую из двух 16-битовых вели-
чин, то структура поместится в 32-битовый регистр.

С++ проектировался для использования в довольно традици-
онной среде компиляции и выполнения, среде программирования
на C в системе UNIX. Средства обработки особых ситуаций и па-
раллельного программирования, требующие нетривиальной загруз-
ки и поддержки в процессе выполнения, не были включены в С++.
Вследствие этого реализация С++ очень легко переносима. Одна-
ко есть полные основания использовать С++ в среде, где имеет-
ся гораздо более существенная поддержка. Такие средства, как
динамическая загрузка, пошаговая трансляция и база данных оп-
ределений типов могут с пользой применяться без воздействия
на язык.

Типы и средства сокрытия данных в С++ опираются на про-
водимый во время компиляции анализ программ с целью предотв-
ращения случайного искажения данных. Они не обеспечивают сек-
ретности или защиты от умышленного нарушения правил. Однако
эти средства можно использовать без ограничений, что не при-
водит к дополнительным расходам времени на выполнение или
пространства памяти.

Исторические Замечания

Безусловно, С++ восходит главным образом к C [7]. C сох-
ранен как подможество, поэтому сделанного в C акцента на
средствах низкого уровня достаточно, чтобы справляться с са-
мыми насущными задачами системного программирования. C, в
свою очередь, многим обязан своему предшественнику BCPL [9].
На самом деле, комментарии // (заново) введены в С++ из BCPL.
Если вы знаете BCPL, то вы заметите, что в С++ по-прежнему
нет VALOF блока. Еще одним источником вдохновения послужил
язык Simula67 [2,3], из него была позаимствована концепция
класса (вместе с производными классами и функциями членами).
Это было сделано, чтобы способствовать модульности через ис-
пользование виртуальных функций. Возможности С++ по перегруз-
ке операций и свобода в расположении описаний везде, где мо-
жет встречаться оператор, похожи на Алгол68 [14].

Название С++ - изобретение совсем недавнее (лета
1983-его). Более ранние версии языка использовались начиная с
1980-ого и были известны как "C с Классами". Первоначально
язык был придуман потому, что автор хотел написать событийно
управляемые модели для чего был бы идеален Simula67, если не
принимать во внимание эффективность. "C с Классами" использо-
вался для крупных проектов моделирования, в которых строго
тестировались возможности написания программ, требующих
(только) минимального пространства памяти и времени на выпол-
нение. В "C с Классами" не хватало перегрузки операций, ссы-
лок, виртуальных функций и многих деталей. С++ был впервые
введен за пределами исследовательской группы автора в июле
1983го. Однако тогда многие особенности С++ были еще не при-


- 5 -
думаны.

Название С++ выдумал Рик Масситти. Название указывает на
эволюционную природу перехода к нему от C. "++" - это опера-
ция приращения в C. Чуть более короткое имя C+ является син-
таксической ошибкой, кроме того, оно уже было использовано
как имя совсем другого языка. Знатоки семантики C находят,
что С++ хуже, чем ++C. Названия D язык не получил, поскольку
он является расширением C и в нем не делается попыток исце-
литься от проблем путем выбрасывания различных особенностей.
Еще одну интерпретацию названия С++ можно найти в приложении
к Оруэллу [8].

Изначально С++ был разработан, чтобы автору и его друзь-
ям не приходилось программировать на ассемблере, C или других
современных языках высокого уровня. Основным его предназначе-
нием было сделать написание хороших программ более простым и
приятным для отдельного программиста. Плана разработки С++ на
бумаге никогда не было. Проект, документация и реализация
двигались одновременно. Разумеется, внешний интерфейс С++ был
написан на С++. Никогда не существовало "Проекта С++" и "Ко-
митета по разработке С++". Поэтому С++ развивался и продолжа-
ет развиваться во всех направлениях, чтобы справляться со
сложностями, с которыми сталкиваются пользователи, а также в
процессе дискуссий автора с его друзьями и коллегами.

В качестве базового языка для С++ был выбран C, потому
что он

[1] многоцелевой, лаконичный и относительно низкого уровня,

[2] отвечает большинству задач системного программирования,

[3] идет везде и на всем и

[4] пригоден в среде программирования UNIX.

В C есть свои сложности, но в наспех спроектированном
языке тоже были бы свои, а сложности C нам известны. Самое
главное, работа с C позволила "C с Классами" быть полезным
(правда, неудобным) инструментом в ходе первых месяцев разду-
мий о добавлении к C Simula-подобных классов.

С++ стал использоваться шире, и по мере того, как воз-
можности, предоставляемые им помимо возможностей C, станови-
лись все более существенными, вновь и вновь поднимался вопрос
о том, сохранять ли совместимость с C. Ясно, что отказавшись
от определенной части наследия C можно было бы избежать ряда
проблем (см., например, Сэти [12]). Это не было сделано, по-
тому что

[1] есть миллионы строк на C, которые могли бы принести
пользу в С++ при условии, что их не нужно было бы полностью
переписывать с C на С++,

[2] есть сотни тысяч строк библиотечных функций и сер-
висных программ, написанных на C, которые можно было бы ис-
пользовать из или на С++ при условии, что С++ полностью сов-
местим с C по загрузке и синтаксически очень похож на C,

[3] есть десятки тысяч программистов, которые знают C, и
которым, поэтому, нужно только научиться использовать новые
особенности С++, а не заново изучать его основы и

[4] поскольку С++ и C будут использоваться на одних и
тех же системах одними и теми же людьми, отличия должны быть
либо очень большими, либо очень маленькими, чтобы свести к


- 6 -
минимуму ошибки и недоразумения.

Позднее была проведена проверка определения С++, чтобы
удостовериться в том, что любая конструкция, допустимая и в C
и в С++, действительно означает в обоих языках одно и то же.

Язык C сам эволюционировал за последние несколько лет,
частично под влиянием развития С++ (см. Ростлер [11]). Пред-
варительный грубый ANSI стандарт C [10] содержит синтаксис
описаний функций, заимствованный из "C с Классами". Заимство-
вание идей идет в обе стороны. Например, указатель void* был
придуман для ANSI C и впервые реализован в С++. Когда ANSI
стандарт разовьется несколько дальше, придет время пересмот-
реть С++, чтобы удалить необоснованную несовместимость. Бу-
дет, например, модернизирован препроцессор (#с.11), и нужно
будет, вероятно, отрегулировать правила выполнения плавающей
арифметики. Это не должно оказаться болезненным, и C и ANSI C
очень близки к тому, чтобы стать подмножествами С++ (см.
#с.11).

Эффективность и Структура

С++ был развит из языка программирования C и за очень
немногими исключениями сохраняет C как подмножество. Базовый
язык, C подмножество С++, спроектирован так, что имеется
очень близкое соответствие между его типами, операциями и
операторами и компьютерными объектами, с которыми непосредс-
твенно приходится иметь дело: числами, символами и адресами.
За исключением операций свободной памяти new и delete, от-
дельные выражения и операторы С++ обычно не нуждаются в скры-
той поддержке во время выполнения или подпрограммах.

В С++ используются те же последовательности вызова и
возврата из функций, что и в C. В тех случаях, когда даже
этот довольно эффективный механизм является слишком дорогим,
С++ функция может быть подставлена inline, удовлетворяя, та-
ким образом, соглашению о записи функций без дополнительных
расходов времени выполнения.

Одним из первоначальных предназначений C было применение
его вместо программирования на ассемблере в самых насущных
задачах системного программирования. Когда проектировался
С++, были приняты меры, чтобы не ставить под угрозу успехи в
этой области. Различие между C и С++ состоит в первую очередь
в степени внимания, уделяемого типам и структурам. C вырази-
телен и снисходителен. С++ еще более выразителен, но чтобы
достичь этой выразительности, программист должен уделить
больше внимания типам объектов. Когда известны типы объектов,
компилятор может правильно обрабатывать выражения, тогда как
в противном случае программисту пришлось бы задавать действия
с мучительными подробностями. Знание типов объектов также
позволяет компилятору обнаруживать ошибки, которые в против-
ном случае остались бы до тестирования. Заметьте, что исполь-
зование системы типов для того, чтобы получить проверку пара-
метров функций, защитить данные от случайного искажения,
задать новые операции и т.д., само по себе не увеличивает
расходов по времени выполнения и памяти.

Особое внимание, уделенное при разработке С++ структуре,
отразилось на возрастании масштаба программ, написанных со
времени разработки C. Маленькую программу (меньше 1000 строк)
вы можете заставить работать с помощью грубой силы, даже на-
рушая все правила хорошего стиля. Для программ больших разме-
ров это не совсем так. Если программа в 10 000 строк имеет
плохую структуру, то вы обнаружите, что новые ошибки появля-
ются так же быстро, как удаляются старые. С++ был разработан
так, чтобы дать возможность разумным образом структурировать


- 7 -
большие программы таким образом, чтобы для одного человека не
было непомерным справляться с программами в 25 000 строк. Су-
ществуют программы гораздо больших размеров, однако те, кото-
рые работают, в целом, как оказывается, состоят из большого
числа почти независимых частей, размер каждой из которых нам-
ного ниже указанных пределов. Естественно, сложность написа-
ния и поддержки программы зависит от сложности разработки, а
не просто от числа строк текста программы, так что точные
цифры, с помощью которых были выражены предыдущие соображе-
ния, не следует воспринимать слишком серьезно.

Не каждая часть программы, однако, может быть хорошо
структурирована, независима от аппаратного обеспечения, легко
читаема и т.п. С++ обладает возможностями, предназначенными
для того, чтобы непосредственно и эффективно работать с аппа-
ратными средствами, не заботясь о безопасности или простоте
понимания. Он также имеет возможности, позволяющие скрывать
такие программы за элегантными и надежными интерфейсами.

В этой книге особый акцент делается на методах создания
универсальных средств, полезных типов, библиотек и т.д. Эти
средства пригодятся как тем программистам, которые пишут не-
большие программы, так и тем, которые пишут большие. Кроме
того, поскольку все нетривиальные программы состоят из боль-
шого числа полунезависимых частей, методы написания таких
частей пригодятся и системным, и прикладным программистам.

У кого-то может появиться подозрение, что спецификация
программы с помощью более подробной системы типов приведет к
увеличению исходных текстов программы. В С++ это не так. С++
программа, описывающая типы параметров функций, использующая
классы и т.д., обычно немного короче эквивалентной C програм-
мы, в которой эти средства не используются.

Философские Замечания

Язык программирования служит двум связанным между собой
целям: он дает программисту аппарат для задания действий, ко-
торые должны быть выполнены, и формирует концепции, которыми
пользуется программист, размышляя о том, что делать. Первой
цели идеально отвечает язык, который настолько "близок к ма-
шине", что всеми основными машинными аспектами можно легко и
просто оперировать достаточно очевидным для программиста об-
разом. С таким умыслом первоначально задумывался C. Второй
цели идеально отвечает язык, который настолько "близок к ре-
шаемой задаче", чтобы концепции ее решения можно было выра-
жать прямо и коротко. С таким умыслом предварительно задумы-
вались средства, добавленные к C для создания С++.

Связь между языком, на котором мы думаем/программируем,
и задачами и решениями, которые мы можем представлять в своем
воображении, очень близка. По этой причине ограничивать
свойства языка только целями исключения ошибок программиста в
лучшем случае опасно. Как и в случае с естественными языками,
есть огромная польза быть по крайней мере двуязычным. Язык
предоставляет программисту набор концептуальных инструментов,
если они не отвечают задаче, то их просто игнорируют. Напри-
мер, серьезные ограничения концепции указателя заставляют
программиста применять вектора и целую арифметику, чтобы реа-
лизовать структуры, указатели и т.п. Хорошее проектирование и
отсутствие ошибок не может гарантироваться чисто за счет язы-
ковых средств.

Система типов должна быть особенно полезна в нетривиаль-
ных задачах. Действительно, концепция классов в С++ показала
себя мощным концептуальным средством.



- 8 -
Размышления о Программировании на С++

В идеальном случае подход к разработке программы делится
на три части: вначале получить ясное понимание задачи, потом
выделить ключевые идеи, входящие в ее решение, и наконец вы-
разить решение в виде программы. Однако подробности задачи и
идеи решения часто становятся ясны только в результате попыт-
ки выразить их в виде программы - именно в этом случае имеет
значение выбор языка программирования.

В большинстве разработок имеются понятия, которые трудно
представить в программе в виде одного из основных типов или
как функцию без ассоциированных с ней статических данных. Ес-
ли имеется подобное понятие, опишите класс, представляющий
его в программе. Класс - это тип, это значит, что он задает
поведение объектов его класса: как они создаются, как может
осуществляться работа с ними, и как они уничтожаются. Класс
также задает способ представления объектов. Но на ранних ста-
диях разработки программы это не является (не должно являть-
ся) главной заботой.
Ключом к написанию хорошей программы является разработка
таких классов, чтобы каждый из них представлял одно основное
понятие. Обычно это означает, что программист должен сосредо-
точиться на вопросах: Как создаются объекты этого класса? Мо-
гут ли эти объекты копироваться и/или уничтожаться? Какие
действия можно производить над этими объектами? Если на такие
вопросы нет удовлетворительных ответов, то во-первых, скорее
всего, понятие не было "ясно", и может быть неплохо еще нем-
ного подумать над задачей и предлагаемым решением, вместо то-
го, чтобы сразу начинать "программировать" сложности.

Проще всего иметь дело с такими понятиями, которые имеют
традиционную математическую форму: числа всех видов, множест-
ва, геометрические фигуры и т.п. На самом деле, следовало бы
иметь стандартные библиотеки классов, представляющих такие
понятия, но к моменту написания это не имело места. С++ еще
молод, и его библиотеки не развились еще до той же степени,
что и сам язык.

Понятие не существует в пустоте, всегда есть группы свя-
занных между собой понятий. Организовать в программе взаимо-
отношения между классами, то есть определить точную взаимос-
вязь между различными понятиями, часто труднее, чем сначала
спланировать отдельные классы. Лучше, чтобы не получилось не-
разберихи, когда каждый класс (понятие) зависит от всех ос-
тальных. Рассмотрим два класса, A и B. Взаимосвязи вроде "A
вызывает функции из B", "A создает объекты B" и "A имеет чле-
ны B" редко вызывают большие сложности, а взаимосвязь вроде
"A использует данные из B" обычно можно исключить (просто не
используйте открытые данные-члены). Неприятными, как правило,
являются взаимосвязи, которые по своей природе имеют вид "A
есть B и ...".

Одним из наиболее мощных интеллектуальных средств, поз-
воляющих преодолевать сложность, является иерархическое упо-
рядочение, то есть организация связанных между собой понятий
в древовидную структуру с самым общим понятием в корне. В С++
такие структуры представляются производными классами. Часто
можно организовать программу как множество деревьев (лес?).
То есть, программист задает множество базовых классов, каждый
из которых имеет свое собственное множество производных клас-
сов. Для определения набора действий для самой общей интерп-
ретации понятия (базового класса) часто можно использовать
виртуальные функции (#7.2.8). Интерпретацию этих действий
можно, в случае необходимости, усовершенствовать для отдель-
ных специальных классов (производных классов).



- 9 -
Естественно, такая организация имеет свои ограничения. В
частности, множество понятий иногда лучше организуется в виде
ациклического графа, в котором понятие может непосредственно
зависеть от более чем одного другого понятия, например, "A
есть B и C и ...". В С++ нет непосредственной поддержки это-
го, но подобные связи можно представить, немного потеряв в
элегантности и проделав малость дополнительной работы
(#7.2.5).

Иногда для организации понятий некоторой программы ока-
зывается непригоден даже ациклический граф, некоторые понятия
оказываются взаимозависимыми по своей природе. Если множество
взаимозависимых классов настолько мало, что его легко себе
представить, то циклические зависимости не должны вызвать
сложностей. Для представления множеств взаимозависимых клас-
сов с С++ можно использовать идею friend классов (#5.4.1).

Если вы можете организовать понятия программы только в
виде общего графа (не дерева или ациклического направленного
графа), и если вы не можете локализовать взаимные зависимос-
ти, то вы, по всей видимости, попали в затруднительное поло-
жение, из которого вас не выручит ни один язык программирова-
ния. Если вы не можете представить какой-либо просто
формулируемой зависимости между основными понятиями, то ско-
рее всего справиться с программой не удастся.

Напомню, что большую часть программирования можно легко
и очевидно выполнять, используя только простые типы, структу-
ры данных, обычные функции и небольшое число классов из стан-
дартной библиотеки. Весь аппарат, входящий в определение но-
вых типов, не следует использовать за исключением тех
случаев, когда он действительно нужен.

Вопрос "Как пишут хорошие программы на С++" очень похож
на вопрос "Как пишут хорошую английскую прозу?" Есть два вида
ответов: "Знайте, что вы хотите сказать" и "Практикуйтесь.
Подражайте хорошему языку." Оба совета оказываются подходящи-
ми к С++ в той же мере, сколь и для английского - и им столь
же трудно следовать.

Правила Правой Руки*

--------------------
* Некоторые легко запоминаемые эмпирические правила. (прим.
перев.)

Здесь приводится набор правил, которых вам хорошо бы
придерживаться изучая С++. Когда вы станете более опытны, вы
можете превратить их в то, что будет подходить для вашего ро-
да деятельности и вашего стиля программирования. Они умышлен-
но сделаны очень простыми, поэтому подробности в них опущены.
Не воспринимайте их чересчур буквально. Написание хороших
программ требует ума, вкуса и терпения. Вы не собираетесь как
следует понять это с самого начала, поэкспериментируйте!

[1] Когда вы программируете, вы создаете конкретное
представление идей вашего решения некоторой задачи. Пусть
структура отражает эти идеи настолько явно, насколько это
возможно:

[a] Если вы считаете "это" отдельным понятием, сделайте его
классом.

[b] Если вы считаете "это" отдельным объектом, сделайте его
объектом некоторого класса.

[c] Если два класса имеют общим нечто существенное, сделайте


- 10 -
его базовым классом. Почти все классы в вашей программе
будут иметь нечто общее. Заведите (почти) универсальный
базовый класс, и разработайте его наиболее тщательно.

[2] Когда вы определяете класс, который не реализует не-
который математический объект, вроде матрицы или комплексного
числа, или тип низкого уровня, вроде связанного списка, то:

[a] Не используйте глобальные данные.

[b] Не используйте глобальные функции (не члены).

[c] Не используйте открытые данные-члены.

[d] Не используйте друзей, кроме как для того, чтобы избе-
жать [a], [b] или [c].

[e] Не обращайтесь к данным-членам или другим объектам
непосредственно.

[f] Не помещайте в класс "поле типа", используйте виртуаль-
ные функции.

[g] Не используйте inline-функции, кроме как средство
существенной оптимизации.

Замечания для Программистов на C

Чем лучше кто-нибудь знает C, тем труднее окажется избе-
жать писания на С++ в стиле C, теряя, тем самым, некоторые
возможные выгоды С++. Поэтому проглядите, пожалуйста, раздел
"Отличия от C" в справочном руководстве (#с.15). Там указыва-
ются области, в которых С++ позволяет делать что-то лучше,
чем C. Макросы (#define) в С++ почти никогда не бывают необ-
ходимы, чтобы определять провозглашаемые константы, исполь-
зуйте const (#2.4.6) или enum (#2.4.7), и inline (#1.12) -
чтобы избежать лишних расходов на вызов функции. Старайтесь
описывать все функции и типы всех параметров - есть очень ма-
ло веских причин этого не делать. Аналогично, практически нет
причин описывать локальную переменную не инициализируя ее,
поскольку описание может появляться везде, где может стоять
оператор, - не описывайте переменную, пока она вам не нужна.
Не используйте malloc() - операция new (#3.2.6) делает ту же
работу лучше. Многие объединения не нуждаются в имени - ис-
пользуйте безымянные объединения (#2.5.2).


Библиографические Ссылки

В тексте мало прямых ссылок на литературу, но здесь при-
веден короткий список книг и статей, которые прямо или кос-
венно упоминаются.

[1] A.V. Aho, J.E. Hopcroft, and J.D. Ulman: Data Structures
and Algorithms. Addison-Wesley, Reading, Massachusetts.
1983.

[2] O-J. Dahl, B. Myrhaug, and K. Nygaard: SIMULA Common Base
Language. Norwegian Computer Center S-22, Oslo, Norsay.
1970

[3] O-J. Dahl and C.A.R. Hoare: Hierarchical Program
Construction in "Structured Programming." Academic Press,
New York. 1972. pp 174-220.

[4] A. Goldberg and D. Robson: SMALLTALK-80 The Language and
Its Implementation. Addison-Wesley, Reading,


- 11 -
Massachusetts. 1983.

[5] R.E. Griswold et.al.: The Snobol4 Programming Language.
Prentice-Hall, Englewood Cliffs, New Jersey. 1970.

[6] R.E. Griswold and M.T. Griswold: The ICON Programming
Language. Prentice-Hall, Englewood Cliffs, New Jersey.
1983.

[7] Brian W. Kernighan and Dennis M. Ritchie: The C
Programming Language. Prentice-Hall, Englewood Cliffs, New
Jersey. 1978. Русский перевод в: Б.В. Керниган, Д. Ритчи,
А. Фьюэр. Язык программирования Си. М.: Финансы и Статис-
тика. 1985.

[8] George Orwell: 1984. Secker and Warburg, London. 1949.
Русский перевод: Дж. Оруэлл. 1984. ...

[9] Martin Richards and Colin Whitby-Strevens: BCPL - The
Language and Its Compiler. Cambridge University Press.
1980.

[10] L. Rosler (Chairman, ANSI X3J11 Language Subcommittee):
Preliminary Draft Proposed Standard - The C Language. X3
Secretariat: Computer and Busineess Equipment
Manufacturers Association, 311 First Street, N.W, Suite
500, Washington, DC 20001, USA.

[11] L.Rosler: The Evolution of C - Past and Future. AT&T
Bell Laboratories Technical Journal. Vol.63 No.8 Part 2.
October 1984. pp 1685-1700.

[12] Ravi Sethi: Uniform Syntax for Type Expressions and
Declarations. Software Practice & Experience, Vol 11
(1981), pp 623-628.

[13] Bjarne Stroustrup: Adding Classes to C: An Exercise in
Language Evolution. Software Practice & Experience, 13
(1981), pp 139-61.

[14] P.M. Woodward and S.G. Bond: Algol 68-R Users Guide. Her
Majesty's Stationery Office, London. 1974.

[15] UNIX System V Release 2.0 User Reference Manual. AT&T
Bell Laboratories, Murray Hill, New Jersey. December 1983.

[16] UNIX Time-Sharing System: Programmer's Manual. Research
Version, Eighth Edition. AT&T Bell Laboratories, Murray
Hill, New Jersey. February 1985.

[17] UNIX Programmer's Manual. 4.2 Berkeley Software
Distribution University of California, Berkeley,
California. March 1984.




- 12 -

Глава 1
Турне по С++

Единственный способ изучать новый язык
программирования - писать на нем программы.
- Брайэн Керниган

Эта глава представляет собой краткий обзор основных черт
языка программирования С++. Сначала приводится программа на С
++, затем показано, как ее откомпилировать и запустить, и как
такая программа может выводить выходные данные и считывать
входные. В первой трети этой главы после введения описаны на-
иболее обычные черты С++: основные типы, описания, выражения,
операторы, функции и структура программы. Оставшаяся часть
главы посвящена возможностям С++ по определению новых типов,
сокрытию данных, операциям, определяемым пользователем, и ие-
рархии определяемых пользователем типов.

1.1 Введение

Это турне проведет вас через ряд программ и частей прог-
рамм на С++. К концу у вас должно сложиться общее представле-
ние об основных особенностях С++, и будет достаточно
информации, чтобы писать простые программы. Для точного и
полного объяснения понятий, затронутых даже в самом маленьком
законченном примере, потребовалось бы несколько страниц опре-
делений. Чтобы не превращать эту главу в описание или в об-
суждение общих понятий, примеры снабжены только самыми корот-
кими определениями используемых терминов. Термины
рассматриваются позже, когда будет больше примеров, способс-
твующих обсуждению.

1.1.1 Вывод

Прежде всего, давайте напишем программу, выводящую стро-
ку выдачи:

#include

main()
(*
cout << "Hello, world\n";
*)

Строка #include сообщает компилятору, чтобы
он включил стандартные возможности потока ввода и вывода, на-
ходящиеся в файле stream.h. Без этих описаний выражение cout
<< "Hello, world\n" не имело бы смысла. Операция << ("помес-
тить в"*) пишет свой первый аргумент во второй (в данном слу-
чае, строку "Hello, world\n" в стандартный поток вывода
cout). Строка - это последовательность символов, заключенная
в двойные кавычки. В строке символ обратной косой \, за кото-
рым следует другой символ, обозначает один специальный сим-
вол, в данном случае, \n является символом новой строки. Та-
ким образом выводимые символы состоят из Hello, world и
перевода строки.

--------------------
* Программирующим на C << известно как операция сдвига
влево для целых. Такое использование << не утеряно, просто в
дальнейшем << было определено для случая, когда его левый
операнд является потоком вывода. Как это делается, описано в
#1.8. (прим. автора)

Остальная часть программы

main() (* ... *)


- 13 -

определяет функцию, названную main. Каждая программа
должна содержать функцию с именем main, и работа программы
начинается с выполнения этой функции.

1.1.2 Компиляция

Откуда появились выходной поток cout и код, реализующий
операцию вывода < ная на С++ программа должна быть скомпилирована. По своей су-
ти процесс компиляции такой же, как и для С, и в нем участву-
ет большая часть входящих в последний программ. Производится
чтение и анализ текста программы, и если не обнаружены ошиб-
ки, то генерируется код. Затем программа проверяется на нали-
чие имен и операций, которые использовались, но не были опре-
делены (в нашем случае это cout и <<). Если это возможно, то
программа делается полной посредством дополнения недостающих
определений из библиотеки (есть стандартные библиотеки, и
пользователи могут создавать свои собственные). В нашем слу-
чае cout и << были описаны в stream.h, то есть, были указаны
их типы, но не было дано никаких подробностей относительно их
реализации. В стандартной библиотеке содержится спецификация
пространства и инициализирующий код для cout и <<. На самом
деле, в этой библиотеке содержится и много других вещей,
часть из которых описана в stream.h, однако к скомпилирован-
ной версии добавляется только подмножество библиотеки, необ-
ходимое для того, чтобы сделать нашу программу полной.

Команда компиляции в С++ обычно называется CC. Она ис-
пользуется так же, как команда cc для программ на C,
подробности вы можете найти в вашем руководстве. Предположим,
что программа с "Hello, world" хранится в файле с именем
hello.c, тогда вы можете ее скомпилировать и запустить при-
мерно так ($ - системное приглашение):

$ CC hello.c
$ a.out
Hello,world
$

a.out - это принимаемое по умолчанию имя исполняемого
результата компиляции. Если вы хотите назвать свою программу,
вы можете сделать это с помощью опции -o:

$ CC hello.c -o hello
$ hello
Hello,world
$

1.1.3 Ввод

Следующая (довольно многословная) программа предлагает
вам ввести число дюймов. После того, как вы это сделаете, она
напечатает соответствующее число сантиметров.

#include

main()
(*
int inch = 0; // inch - дюйм
cout << "inches";
cin >> inch;
cout << inch;
cout << " in = ";
cout << inch*2.54;
cout << " cm\n";
*)


- 14 -

Первая строка функции main() описывает целую переменную
inch. Ее значение считывается с помощью операции >> ("взять
из") над стандартным потоком ввода cin. Описания cin и >>,
конечно же, находятся в . После ее запуска ваш тер-
минал может выглядеть примерно так:

$ a.out
inches=12
12 in = 30.48 cm
$

В этом примере на каждую команду вывода приходится один
оператор. Это слишком длинно. Операцию вывода << можно приме-
нять к ее собственному результату, так что последние четыре
команды вывода можно было записать одним оператором:

cout << inch << " in = " << inch*2.54 << " cm\n";

В последующих разделах ввод и вывод будут описаны гораз-
до более подробно. Вся эта глава фактически может рассматри-
ваться как объяснение того, как можно написать предыдущие
программы на языке, который не обеспечивает операции вво-
да-вывода. На самом деле, приведенные выше программы написаны
на С++, "расширенном" операциями ввода-вывода посредством ис-
пользования библиотек и включения файлов с помощью #include.
Другими словами, язык С++ в том виде, в котором он описан в
справочном руководстве, не определяет средств ввода-вывода.
Вместо этого исключительно с помощью средств, доступных любо-
му программисту, определены операции << и >>.

1.2 Комментарии

Часто бывает полезно вставлять в программу текст, кото-
рый предназначается в качестве комментария только для читаю-
щего программу человека и игнорируется компилятором в
программе. В С++ это можно сделать одним из двух способов.

Символы /* начинают комментарий, заканчивающийся симво-
лами */. Вся эта последовательность символов эквивалентна
символу пропуска (например, символу пробела). Это наиболее
полезно для многострочных комментариев и изъятия частей прог-
раммы при редактировании, однако следует помнить, что коммен-
тарии /* */ не могут быть вложенными.

Символы // начинают комментарий, который заканчивается в
конце строки, на которой они появились. Опять, вся последова-
тельность символов эквивалентна пропуску. Этот способ наибо-
лее полезен для коротких комментариев. Символы // можно ис-
пользовать для того, чтобы закомментировать символы /* или
*/, а символами /* можно закомментировать //.

1.3 Типы и Описания

Каждое имя и каждое выражение имеет тип, определяющий
операции, которые могут над ними производиться. Например,
описание

int inch;

определяет, что inch имеет тип int, то есть, inch явля-
ется целой переменной.

Описание - это оператор, который вводит имя в программе.
Описание задает тип этого имени. Тип определяет правильное
использование имени или выражения. Для целых определены такие
операции, как +, -, * и /. После того, как включен файл


- 15 -
stream.h, объект типа int может также быть вторым операндом
<<, когда первый операнд ostream.
Тип объекта определяет не только то, какие операции мо-
гут к нему применяться, но и смысл этих операций. Например,
оператор

cout << inch << " in = " << inch*2.54 << " cm\n";

правильно обрабатывает четыре входных значения различным
образом. Строки печатаются буквально, тогда как целое inch и
значение с плавающей точкой inch*2.54 преобразуются из их
внутреннего представления в подходящее для человеческого гла-
за символьное представление.

В С++ есть несколько основных типов и несколько способов
создавать новые. Простейшие виды типов С++ описываются в сле-
дующих разделах, а более интересные оставлены на потом.

1.3.1 Основные Типы

Основные типы, наиболее непосредственно отвечающие
средствам аппаратного обеспечения, такие:

char short int long float double


назад |  1  2 3 4 5 6 7 | вперед


Назад


Новые поступления

Украинский Зеленый Портал Рефератик создан с целью поуляризации украинской культуры и облегчения поиска учебных материалов для украинских школьников, а также студентов и аспирантов украинских ВУЗов. Все материалы, опубликованные на сайте взяты из открытых источников. Однако, следует помнить, что тексты, опубликованных работ в первую очередь принадлежат их авторам. Используя материалы, размещенные на сайте, пожалуйста, давайте ссылку на название публикации и ее автора.

281311062 © insoft.com.ua,2007г. © il.lusion,2007г.
Карта сайта