                                 Заметки для Читателя
           
                                         "О многом," - молвил Морж,  - "Пришла
                                                            пора поговорить."
                                                                  - Л. Кэррол
           
             В этой главе содержится  обзор  книги,  список  библиографических
           ссылок и некоторые замечания по С++ вспомогательного характера. За-
           мечания касаются истории С++, идей, оказавших влияние на разработку
           С++, и мыслей по поводу программирования на С++. Эта глава не явля-
           ется введением:  замечания не обязательны для понимания последующих
           глав, и некоторые из них предполагают знание С++.
                Структура Этой Книги
           
             Глава 1 - это короткое турне по основным особенностям С++,  пред-
           назначенное для того, чтобы дать читателю почувствовать язык. Прог-
           раммисты на C первую половину главы могут прочитать  очень  быстро,
           она охватывает главным образом черты,  общие для C и С++. Во второй
           главе описаны средства определения новых типов  в  С++,  начинающие
           могут отложить более подробное изучение этого до того,  как прочтут
           Главы 2, 3 и 4.
           
             В Главах 2, 3 и 4 описываются средства С++, не входящие в опреде-
           ление новых типов:  основные типы, выражения и структуры управления
           в С++ программах.  Другими словами,  в них описывается подмножество
           С++, которое по существу является языком C. Рассмотрение в них про-
           водится гораздо подробнее,  но полную информацию можно найти только
           в справочном руководстве.
           
             В Главах 5,  6 и 7 описываются средства С++ по описанию новых ти-
           пов,  особенности языка, не имеющие эквивалента в C. В Главе 5 при-
           водится понятие базового класса,  и показывается, как можно инициа-
           лизировать объекты типа,  определяемого пользователем, обращаться к
           ним и,  наконец, убирать их. В Главе 6 объясняется, как для опреде-
           ляемого пользователем типа определять унарные и бинарные  операции,
           как задавать преобразования между типами, определяемыми пользовате-
           лем,  и как как задавать то,  каким образом  должно  обрабатываться
           каждое  создание,  уничтожение и копирование значения определяемого
           пользователем  типа.  Глава  7  описывает   концепцию   производных
           классов,  которая  позволяет  программисту  строить  более  сложные
           классы из более  простых,  обеспечивать  альтернативные  интерфейсы
           класса  и  работать с объектами эффективно и с гарантией типа в тех
           ситуациях,  когда типы объектов не могут быть  известны  на  стадии
           компиляции.
           
             В Главе 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.
           
             В С++  нет  типов данных высокого уровня и нет первичных операций
           высокого уровня.  В нем нет,  например, матричного типа с операцией
           обращения или типа строка с операцией конкатенации.  Если пользова-
           телю понадобятся подобные типы,  их можно определить в самом языке.
           По  сути дела,  основное,  чем занимается программирование на С++ -
           это определение универсальных и специально-прикладных типов. Хорошо
           разработанный тип, определяемый пользователем, отличается от встро-
           енного типа только способом определения, но не способом использова-
           ния.
           
             Исключались те  черты,  которые  могли  бы повлечь дополнительные
           расходы памяти или времени выполнения. Например, мысли о том, чтобы
           сделать  необходимым  хранение в каждом объекте "хозяйственной" ин-
           формации,  были отвергнуты.  Если пользователь описывает структуру,
           состоящую  из  двух  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его.  Однако
           тогда многие особенности С++ были еще не придуманы.
           
             Название С++ выдумал Рик Масситти. Название указывает на эволюци-
           онную природу перехода к нему от 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 будут использоваться на одних и тех же
                  системах одними и теми же людьми,  отличия должны быть  либо
                  очень большими,  либо очень маленькими, чтобы свести к мини-
                  муму ошибки и недоразумения.
           
             Позднее была проведена проверка определения С++,  чтобы удостове-
           риться  в  том,  что  любая конструкция,  допустимая и в 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 строк имеет плохую структуру,  то вы обнаружите,
           что  новые  ошибки появляются так же быстро,  как удаляются старые.
           С++ был разработан так,  чтобы дать  возможность  разумным  образом
           структурировать  большие программы таким образом,  чтобы для одного
           человека не было непомерным справляться  с  программами  в  25  000
           строк.  Существуют  программы гораздо больших размеров,  однако те,
           которые работают,  в целом,  как оказывается,  состоят из  большого
           числа  почти  независимых частей,  размер каждой из которых намного
           ниже указанных пределов.  Естественно,  сложность написания и  под-
           держки  программы  зависит от сложности разработки,  а не просто от
           числа строк текста программы, так что точные цифры, с помощью кото-
           рых  были выражены предыдущие соображения,  не следует воспринимать
           слишком серьезно.
             Не каждая часть программы, однако, может быть хорошо структуриро-
           вана,  независима от аппаратного обеспечения,  легко читаема и т.п.
           С++  обладает возможностями,  предназначенными для того,  чтобы не-
           посредственно и эффективно работать с  аппаратными  средствами,  не
           заботясь о безопасности или простоте понимания. Он также имеет воз-
           можности, позволяющие скрывать такие программы за элегантными и на-
           дежными интерфейсами.
           
             В этой  книге  особый  акцент  делается  на методах создания уни-
           версальных средств,  полезных типов,  библиотек и т.д. Эти средства
           пригодятся как тем программистам,  которые пишут небольшие програм-
           мы,  так и тем,  которые пишут большие.  Кроме того,  поскольку все
           нетривиальные  программы  состоят из большого числа полунезависимых
           частей,  методы написания таких частей пригодятся  и  системным,  и
           прикладным программистам.
           
             У кого-то может появиться подозрение,  что спецификация программы
           с помощью более  подробной  системы  типов  приведет  к  увеличению
           исходных текстов программы. В С++ это не так. С++ программа, описы-
           вающая типы параметров функций,  использующая классы и т.д., обычно
           немного короче эквивалентной C программы, в которой эти средства не
           используются.
           
                Философские Замечания
           
             Язык программирования служит двум связанным между собой целям:
           он дает  программисту аппарат для задания действий,  которые должны
           быть выполнены, и формирует концепции, которыми пользуется програм-
           мист,  размышляя о том,  что делать.  Первой цели идеально отвечает
           язык,  который настолько "близок к машине", что всеми основными ма-
           шинными  аспектами можно легко и просто оперировать достаточно оче-
           видным для программиста образом.  С таким умыслом первоначально за-
           думывался C.  Второй цели идеально отвечает язык, который настолько
           "близок к решаемой задаче",  чтобы концепции ее решения можно  было
           выражать прямо и коротко.  С таким умыслом предварительно задумыва-
           лись средства, добавленные к C для создания С++.
           
             Связь между языком, на котором мы думаем/программируем, и задача-
           ми и решениями,  которые мы можем представлять в своем воображении,
           очень близка.  По этой причине ограничивать свойства  языка  только
           целями исключения ошибок программиста в лучшем случае опасно. Как и
           в случае с естественными языками,  есть  огромная  польза  быть  по
           крайней мере двуязычным. Язык предоставляет программисту набор кон-
           цептуальных инструментов, если они не отвечают задаче, то их просто
           игнорируют.  Например,  серьезные  ограничения  концепции указателя
           заставляют программиста применять вектора и целую арифметику, чтобы
           реализовать  структуры,  указатели и т.п.  Хорошее проектирование и
           отсутствие ошибок не может гарантироваться чисто за  счет  языковых
           средств.
           
             Система типов  должна быть особенно полезна в нетривиальных зада-
           чах.  Действительно,  концепция классов в С++ показала себя  мощным
           концептуальным средством.
                Размышления о Программировании на С++
           
             В идеальном случае подход к разработке программы делится  на  три
           части: вначале получить ясное понимание задачи, потом выделить клю-
           чевые идеи, входящие в ее решение, и наконец выразить решение в ви-
           де программы. Однако подробности задачи и идеи решения часто стано-
           вятся ясны только в результате попытки выразить их в виде программы
           - именно в этом случае имеет значение выбор языка программирования.
           
             В большинстве разработок имеются понятия, которые трудно предста-
           вить в программе в виде одного из основных типов  или  как  функцию
           без ассоциированных с ней статических данных. Если имеется подобное
           понятие, опишите класс, представляющий его в программе. Класс - это
           тип,  это значит,  что он задает поведение объектов его класса: как
           они создаются,  как может осуществляться работа с ними,  и как  они
           уничтожаются.  Класс также задает способ представления объектов. Но
           на ранних стадиях разработки программы это не является  (не  должно
           являться) главной заботой. Ключом к написанию хорошей программы яв-
           ляется разработка таких классов,  чтобы каждый из  них  представлял
           одно основное понятие.  Обычно это означает, что программист должен
           сосредоточиться на вопросах:  Как создаются объекты  этого  класса?
           Могут   ли  эти  объекты  копироваться  и/или  уничтожаться?  Какие
           действия можно производить над этими объектами?  Если на такие воп-
           росы  нет удовлетворительных ответов,  то во-первых,  скорее всего,
           понятие не было "ясно",  и может быть неплохо еще немного  подумать
           над задачей и предлагаемым решением, вместо того, чтобы сразу начи-
           нать "программировать" сложности.
           
             Проще всего иметь дело с такими понятиями, которые имеют традици-
           онную математическую форму:  числа всех видов, множества, геометри-
           ческие фигуры и т.п.  На самом деле, следовало бы иметь стандартные
           библиотеки классов,  представляющих такие понятия, но к моменту на-
           писания это не имело места. С++ еще молод, и его библиотеки не раз-
           вились еще до той же степени, что и сам язык.
           
             Понятие не  существует  в  пустоте,  всегда есть группы связанных
           между собой понятий. Организовать в программе взаимоотношения между
           классами,  то  есть  определить точную взаимосвязь между различными
           понятиями,  часто  труднее,  чем  сначала  спланировать   отдельные
           классы.  Лучше, чтобы не получилось неразберихи, когда каждый класс
           (понятие) зависит от всех остальных.  Рассмотрим два класса, A и B.
           Взаимосвязи вроде "A вызывает функции из B",  "A создает объекты B"
           и "A имеет члены B" редко вызывают большие сложности, а взаимосвязь
           вроде  "A использует данные из B" обычно можно исключить (просто не
           используйте открытые данные-члены). Неприятными, как правило, явля-
           ются  взаимосвязи,  которые  по своей природе имеют вид "A есть B и
           ...".
           
             Одним из наиболее мощных  интеллектуальных  средств,  позволяющих
           преодолевать  сложность,  является  иерархическое упорядочение,  то
           есть организация связанных между собой понятий в древовидную струк-
           туру  с  самым  общим  понятием  в  корне.  В  С++  такие структуры
           представляются  производными  классами.  Часто  можно  организовать
           программу как множество деревьев (лес?). То есть, программист зада-
           ет  множество  базовых  классов,  каждый  из  которых  имеет   свое
           собственное  множество производных классов.  Для определения набора
           действий для самой общей интерпретации  понятия  (базового  класса)
           часто можно использовать виртуальные функции (#7.2.8).  Интерпрета-
           цию этих действий можно,  в случае необходимости, усовершенствовать
           для отдельных специальных классов (производных классов).
             Естественно, такая организация имеет свои  ограничения.  В  част-
           ности,  множество  понятий иногда лучше организуется в виде ацикли-
           ческого графа,  в котором понятие может непосредственно зависеть от
           более чем одного другого понятия, например, "A есть B и C и ...". В
           С++ нет непосредственной поддержки этого,  но подобные связи  можно
           представить,  немного потеряв в элегантности и проделав малость до-
           полнительной работы (#7.2.5).
           
             Иногда для организации понятий  некоторой  программы  оказывается
           непригоден  даже  ациклический граф,  некоторые понятия оказываются
           взаимозависимыми по своей природе.  Если множество  взаимозависимых
           классов настолько мало,  что его легко себе представить,  то цикли-
           ческие зависимости не должны вызвать сложностей.  Для представления
           множеств  взаимозависимых  классов  с  С++  можно использовать идею
           friend классов (#5.4.1).
           
             Если вы можете организовать понятия программы только в виде обще-
           го графа (не дерева или ациклического направленного графа),  и если
           вы не можете локализовать взаимные зависимости,  то вы, по всей ви-
           димости, попали в затруднительное положение, из которого вас не вы-
           ручит ни один язык программирования.  Если вы не можете представить
           какой-либо просто формулируемой зависимости между основными поняти-
           ями, то скорее всего справиться с программой не удастся.
           
             Напомню, что большую часть программирования можно легко и очевид-
           но  выполнять,  используя  только  простые типы,  структуры данных,
           обычные функции и небольшое число классов из стандартной  библиоте-
           ки.  Весь аппарат,  входящий в определение новых типов,  не следует
           использовать за исключением тех случаев, когда он действительно ну-
           жен.
           
             Вопрос "Как пишут хорошие программы на С++" очень похож на вопрос
           "Как пишут хорошую английскую прозу?" Есть два вида ответов: "Знай-
           те,  что  вы хотите сказать" и "Практикуйтесь.  Подражайте хорошему
           языку." Оба совета оказываются подходящими к С++  в  той  же  мере,
           сколь и для английского - и им столь же трудно следовать.
           
                Правила Правой Руки*
           
             Здесь приводится  набор  правил,  которых вам хорошо бы придержи-
           ваться изучая С++. Когда вы станете более опытны, вы можете превра-
           тить  их  в то,  что будет подходить для вашего рода деятельности и
           вашего стиля программирования.  Они умышленно сделаны очень просты-
           ми, поэтому подробности в них опущены. Не воспринимайте их чересчур
           буквально.  Написание хороших программ требует ума,  вкуса и терпе-
           ния.  Вы не собираетесь как следует понять это с самого начала, по-
           экспериментируйте!
           
           ────────────────────
           * Некоторые легко запоминаемые эмпирические правила. (прим.
           перев.) [1] Когда вы программируете, вы создаете конкретное
                представление идей  вашего  решения  некоторой  задачи.  Пусть
                структура отражает эти идеи настолько явно, насколько это воз-
                можно:
           
                [a] Если  вы  считаете "это" отдельным понятием,  сделайте его
                     классом.
           
                [b] Если вы считаете "это" отдельным  объектом,  сделайте  его
                     объектом некоторого класса.
           
                [c] Если  два класса имеют общим нечто существенное,  сделайте
                     его базовым классом.  Почти все классы в вашей  программе
                     будут  иметь нечто общее.  Заведите (почти) универсальный
                     базовый класс, и разработайте его наиболее тщательно.
           
             [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, 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.
