Парадигмы программирования




ПРЕДВАРИТЕЛЬНЫЕ ЗАМЕЧАНИЯ

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

Структура книги

Книга состоит из трех частей. Главы с 1 по 10 являются учебником поязыку. В главах с 11 по 13 обсуждаются вопросы проектирования и развитияпрограммного обеспечения с учетом возможностей С++. В конце книгиприведено полное справочное руководство по языку. Исчерпывающее описаниеконструкций С++ содержится только там. Учебная часть книги содержитпримеры, советы, предостережения и упражнения, для которых не нашлосьместа в руководстве. Книга в основном посвящена вопросу, как с помощью языка C++структурировать программу, а не вопросу, как записать на нем алгоритм.Следовательно, там, где можно было выбирать, предпочтение отдавалось непрофессиональным, но сложным для понимания, а тривиальным алгоритмам. Такв одном из примеров используется пузырьковая сортировка, хотя алгоритмбыстрой сортировки больше подходит для настоящей программы. Частонаписать ту же программу, но с более эффективным алгоритмом, предлагаетсяв виде упражнения. Глава 1 содержит краткий обзор основных концепций и конструкций С++.Она позволяет познакомиться с языком в общих чертах. Подробные объясненияконструкций языка и способов их применения содержатся в последующихглавах. Обсуждаются в первую очередь средства, обеспечивающие абстракциюданных и объектно-ориентированное программирование. Основные средствапроцедурного программирования упоминаются кратко. В главах 2, 3 и 4 описываются средства С++, которые не используютсядля определения новых типов: основные типы, выражения и структурыуправления. Другими словами, эти главы содержат описание той части языка,которая по сути представляет С. Изложение в указанных главах идет вуглубленном виде. Главы 5 - 8 посвящены средствам построения новых типов, которые неимеют аналогов в С. В главе 5 вводится основное понятие - класс. В нейпоказано, как можно определять пользовательские типы (классы),инициализировать их, обращаться к ним, и, наконец, как уничтожать их.Глава 6 посвящена понятию производных классов, которое позволяет строитьиз простых классов более сложные. Оно дает также возможность эффективной ибезопасной (в смысле типа) работы в тех ситуациях, когда типы объектов настадии трансляции неизвестны. В главе 7 объясняется, как можно определитьунарные и бинарные операции для пользовательских типов, как задаватьпреобразования таких типов, и каким образом можно создавать, копировать иудалять объекты, представляющие пользовательские типы. Глава 8 посвященашаблонам типа, т.е. такому средству С++, которое позволяет определитьсемейство типов и функций. В главе 9 обсуждается обработка особых ситуаций, рассматриваютсявозможные реакции на ошибки и методы построения устойчивых к ошибкамсистем. В главе 10 определяются классы ostream и istream, предоставляемыестандартной библиотекой для потокового ввода-вывода. Главы 11 - 13 посвящены вопросам, связанным с применением С++ дляпроектирования и реализации больших программных систем. В главе 11 восновном рассматриваются вопросы проектирования и управления программнымипроектами. В главе 12 обсуждается взаимосвязь между языком С++ ипроблемами проектирования. В главе 13 показаны способы создания библиотек. Завершается книга справочным руководством по С++. Ссылки на различные части книги даются в виде $$2.3.4, что означаетраздел 3.4 главы 2. Для обозначения справочного руководства применяетсябуква R, например, $$R.8.5.5. Замечания по реализации Существует несколько распространяемых независимых реализаций С++.Появилось большое число сервисных программ, библиотек и интегрированныхсистем программирования. Имеется масса книг, руководств, журналов, статей,сообщений по электронной почте, технических бюллетеней, отчетов оконференциях и курсов, из которых можно получить все необходимые сведенияо последних изменениях в С++, его использовании, сервисных программах,библиотеках, новых трансляторах и т.д. Если вы серьезно рассчитываете наС++, стоит получить доступ хотя бы к двум источникам информации, посколькуу каждого источника может быть своя позиция. Большинство программных фрагментов, приведенных в книге, взятынепосредственно из текстов программ, которые были транслированы на машинеDEC VAX 11/8550 под управлением 10-й версии системы UNIX [25].Использовался транслятор, являющийся прямым потомком транслятора С++,созданного автором. Здесь описывается "чистый С++", т.е. не используютсяникакие зависящие от реализации расширения. Следовательно, примеры должныидти при любой реализации языка. Однако, шаблоны типа и обработка особыхситуаций относятся к самым последним расширениям языка, и возможно, чтоваш транслятор их не содержит. Упражнения Упражнения даются в конце каждой главы. Чаще всего они предлагаютнаписать программу. Решением может считаться программа, котораятранслируется и правильно работает хотя бы на нескольких тестах.Упражнения могут значительно различаться по сложности, поэтому даетсяприблизительная оценка степени их сложности. Рост сложностиэкспоненциальный, так что, если на упражнение (*1) у вас уйдет пять минут,то (*2) может занять час, а (*3) - целый день. Однако время написания иотладки программы больше зависит от опыта читателя, чем от самогоупражнения. На упражнение (*1) может потребоваться целый день, если передзапуском программы читателю придется ознакомиться с новой вычислительнойсистемой. С другой стороны, тот, у кого под рукой окажется нужный наборпрограмм, может сделать упражнение (*5) за один час. Любую книгу по программированию на языке С можно использовать какисточник дополнительных упражнений при изучении глав 2 - 4. В книге Ахо([1]) приведено много общих структур данных и алгоритмов в терминахабстрактных типов данных. Эту книгу также можно использовать как источникупражнений при изучении глав 5 - 8. Однако, использованному в ней языку недостает функций-членов и производных классов. Поэтому определяемыепользователем типы на С++ можно написать более элегантно. Замечания по проекту языка При разработке языка С++ одним из важнейших критериев выбора былапростота. Когда возникал вопрос, что упростить: руководство по языку идругую документацию или транслятор, - то выбор делали в пользу первого.Огромное значение придавалось совместимости с языком С, что помешалоудалить его синтаксис. В С++ нет типов данных и элементарных операций высокого уровня.Например, не существует типа матрица с операцией обращения или типа строкас операцией конкатенации. Если пользователю понадобятся подобные типы, онможет определить их в самом языке. Программирование на С++ по сутисводится к определению универсальных или зависящих от области приложениятипов. Хорошо продуманный пользовательский тип отличается от встроенноготипа только способом определения, но не способом применения. Из языка исключались возможности, которые могут привести к накладнымрасходам памяти или времени выполнения, даже если они непосредственно неиспользуются в программе. Например, было отвергнуто предложение хранить вкаждом объекте некоторую служебную информацию. Если пользователь описалструктуру, содержащую две величины, занимающие по 16 разрядов, тогарантируется, что она поместится в 32-х разрядный регистр. Язык С++ проектировался для использования в довольно традиционнойсреде, а именно: в системе программирования С операционной системы UNIX.Но есть вполне обоснованные доводы в пользу использования С++ в болеебогатой программной среде. Такие возможности, как динамическая загрузка,развитые системы трансляции и базы данных для хранения определений типов,можно успешно использовать без ущерба для языка. Типы С++ и механизмы упрятывания данных рассчитаны на определенныйсинтаксический анализ, проводимый транслятором для обнаружения случайнойпорчи данных. Они не обеспечивают секретности данных и защиты отумышленного нарушения правил доступа к ним. Однако, эти средства можносвободно использовать, не боясь накладных расходов памяти и временивыполнения программы. Учтено, что конструкция языка активно используетсятогда, когда она не только изящно записывается на нем, но и вполне посредствам обычным программам. Историческая справка Безусловно С++ многим обязан языку С [8], который сохраняется как егоподмножество. Сохранены и все свойственные С средства низкого уровня,предназначенные для решения самых насущных задач системногопрограммирования. С, в свою очередь, многим обязан своему предшественникуязыку BCPL [13]. Комментарий языка BCPL был восстановлен в С++. Есличитатель знаком с языком BCPL, то может заметить, что в С++ по-прежнемунет блока VALOF. Еще одним источником вдохновения был язык SIMULA-67[2,3]; именно из него была заимствована концепция классов (вместе cпроизводными классами и виртуальными функциями). Оператор inspect изSIMULA-67 намеренно не был включен в С++. Причина - желаниеспособствовать модульности за счет использования виртуальных функций.Возможность в С++ перегрузки операций и свобода размещения описаний всюду,где может встречаться оператор, напоминают язык Алгол-68 [24]. С момента выхода в свет первого издания этой книги язык С++ подвергсясущественным изменениям и уточнениям. В основном это касается разрешениянеоднозначности при перегрузке, связывании и управлении памятью. Вместе стем, были внесены незначительные изменения с целью увеличить совместимостьс языком С. Были также введены некоторые обобщения и существенныерасширения, как то: множественное наследование, функции-члены соспецификациями static и const, защищенные члены (protected), шаблоны типаи обработка особых ситуаций. Все эти расширения и доработки были нацеленына то, чтобы С++ стал языком, на котором можно создавать и использоватьбиблиотеки. Все изменения описываются в [10,18,20,21 и 23]. Шаблоны типов появились частично из-за желания формализоватьмакросредства, а частично были инспирированы описанием генерическихобъектов в языке Ада (с учетом их достоинств и недостатков) ипараметризированными модулями языка CLU. Механизм обработки особыхситуаций появился отчасти под влиянием языков Ада и CLU [11], а отчастипод влиянием ML [26]. Другие расширения, введенные за период между 1985 и1991 г.г. (такие как множественное наследование, статические функции-членыи чистые виртуальные функции), скорее появились в результате обобщенияопыта программирования на С++, чем были почерпнуты из других языков. Более ранние версии языка, получившие название "С с классами" [16],использовались, начиная с 1980 г. Этот язык возник потому, что авторупотребовалось написать программы моделирования, управляемые прерываниями.Язык SIMULA-67 идеально подходит для этого, если не учитыватьэффективность. Язык "С с классами" использовался для больших задачмоделирования. Строгой проверке подверглись тогда возможности написания нанем программ, для которых критичны ресурсы времени и памяти. В этом языкенедоставало перегрузки операций, ссылок, виртуальных функций и многихдругих возможностей. Впервые С++ вышел за пределы исследовательскойгруппы, в которой работал автор, в июле 1983 г., однако тогда многиевозможности С++ еще не были разработаны. Название С++ (си плюс плюс), было придумано Риком Маскитти летом 1983г. Это название отражает эволюционный характер изменений языка С.Обозначение ++ относится к операции наращивания С. Чуть более короткое имяС+ является синтаксической ошибкой. Кроме того, оно уже было использованокак название совсем другого языка. Знатоки семантики С находят, что С++хуже, чем ++С. Язык не получил названия D, поскольку он являетсярасширением С, и в нем не делается попыток решить какие-либо проблемы засчет отказа от возможностей С. Еще одну интересную интерпретацию названияС++ можно найти в приложении к [12]. Изначально С++ был задуман для того, чтобы автору и его друзьям ненадо было программировать на ассемблере, С или других современных языкахвысокого уровня. Основное его предназначение - упростить и сделать болееприятным процесс программирования для отдельного программиста. Донедавнего времени не было плана разработки С++ на бумаге. Проектирование,реализация и документирование шли параллельно. Никогда не существовало"проекта С++" или "Комитета по разработке С++". Поэтому язык развивался ипродолжает развиваться так, чтобы преодолеть все проблемы, с которымистолкнулись пользователи. Толчками к развитию служат также и обсужденияавтором всех проблем с его друзьями и коллегами. В связи с лавинообразным процессом увеличения числа пользователей С++,пришлось сделать следующие изменения. Примерно в 1987 г. стало очевидно,что работа по стандартизации С++ неизбежна и что следует незамедлительноприступить к созданию основы для нее [22]. В результате были предпринятыцеленаправленные действия, чтобы установить контакт между разработчикамиС++ и большинством пользователей. Применялась обычная и электроннаяпочта, а также было непосредственное общение на конференциях по С++ идругих встречах. Фирма AT&T Bell Laboratories внесла основной вклад в эту работу,предоставив автору право изучать версии справочного руководства по языкувместе с упоминавшимися разработчиками и пользователями. Не следуетнедооценивать этот вклад, т.к. многие из них работают в компаниях, которыеможно считать конкурентами фирмы AT&T. Менее просвещенная компания моглабы просто ничего не делать, и в результате появилось бы нескольконесогласованных версий языка. Около ста представителей из порядка 20организаций изучали и комментировали то, что стало современной версиейсправочного руководства и исходными материалами для ANSI по стандартизацииС++. Их имена можно найти в "Аннотированном справочном руководстве поязыку С++" [4]. Справочное руководство полностью вошло в настоящую книгу.Наконец, по инициативе фирмы Hewlett-Packard в декабре 1989 г. в составеANSI был образован комитет X3J16. Ожидается, что работы по стандартизацииС++ в ANSI (американский стандарт) станут составной частью работ постандартизации силами ISO (Международной организации по стандартизации). С++ развивался одновременно с развитием некоторых фундаментальныхклассов, представленных в данной книге. Например, автор разрабатывалклассы complex, vector и stack, создавая одновременно возможностьперегрузки операций. В результате этих же усилий и благодаря содействиюД. Шапиро появились строковые и списочные классы. Эти классы стали первымибиблиотечными классами, которые начали активно использоваться. Библиотекаtask, описываемая в [19] и в упражнении 13 из $$6.8 стала частью самойпервой программы, написанной на языке "С с классами". Эта программа ииспользуемые в ней классы были созданы для моделирования в стиле Симулы.Библиотека task была существенно переработана Д. Шапиро и продолжаетактивно использоваться до настоящего времени. Потоковая библиотека, какуказывалось в первом издании книги, была разработана и применена автором.Д. Шварц преобразовал ее в потоковую библиотеку ввода-вывода ($$10),используя наряду с другими приемами метод манипуляторов Э.Кенига($$10.4.2). Класс map ($$8.8) был предложен Э.Кенигом. Он же создал классPool ($$13.10), чтобы использовать для библиотеки предложенный авторомспособ распределения памяти для классов ($$5.5.6). На создание остальныхшаблонов повлияли шаблоны Vector, Map, Slist и sort, представленные вглаве 8. Сравнение языков С++ и С Выбор С в качестве базового языка для С++ объясняется следующими егодостоинствами: (1) универсальность, краткость и относительно низкий уровень;(2) адекватность большинству задач системного программирования;(3) он идет в любой системе и на любой машине;(4) полностью подходит для программной среды UNIX. В С существуют свои проблемы, но в языке, разрабатываемом "с нуля" онипоявились бы тоже, а проблемы С, по крайней мере, хорошо известны. Болееважно то, что ориентация на С позволила использовать язык "С с классами"как полезный (хотя и не очень удобный) инструмент в течение первых месяцевраздумий о введении в С классов в стиле Симулы. С++ стал использоваться шире, но по мере роста его возможностей,выходящих за пределы С, вновь и вновь возникала проблема совместимости.Ясно, что отказавшись от части наследства С, можно избежать некоторыхпроблем (см., например, [15]). Это не было сделано по следующим причинам: (1) существуют миллионы строк программ на С, которые можно улучшить спомощью С++, но при условии, что полной переписи их на язык С++ непотребуется; (2) существуют миллионы строк библиотечных функций и служебныхпрограмм на С, которые можно было бы использовать в С++ при условияхсовместимости обоих языков на стадии связывания и их большогосинтаксического сходства; (3) существуют сотни тысяч программистов, знающих С; им достаточноовладеть только новыми средствами С++ и не надо изучать основ языка; (4) поскольку С и С++ будут использоваться одними и теми же людьми наодних и тех же системах многие годы, различия между языками должны бытьлибо минимальными, либо максимальными, чтобы свести к минимуму количествоошибок и недоразумений. Описание С++ было переработано так, чтобыгарантировать, что любая допустимая в обоих языках конструкция означала вних одно и то же. Язык С сам развивался в последние несколько лет, что отчасти былосвязано с разработкой С++ [14]. Стандарт ANSI для С [27] содержит,например, синтаксис описания функций, позаимствованный из языка "С склассами". Происходит взаимное заимствование, например, тип указателяvoid* был придуман для ANSI С, а впервые реализован в С++. Как былообещано в первом издании этой книги, описание С++ было доработано, чтобыисключить неоправданные расхождения. Теперь С++ более совместим с языкомС, чем это было вначале ($$R.18). В идеале С++ должен максимальноприближаться к ANSI C, но не более [9]. Стопроцентной совместимостиникогда не было и не будет, поскольку это нарушит надежность типов исогласованность использования встроенных и пользовательских типов, а этисвойства всегда были одними из главных для С++. Для изучения С++ не обязательно знать С. Программирование на Сспособствует усвоению приемов и даже трюков, которые при программированиина С++ становятся просто ненужными. Например, явное преобразование типа(приведение), в С++ нужно гораздо реже, чем в С (см. "Замечания дляпрограммистов на С" ниже). Тем не менее, хорошие программы на языке С посути являются программами на С++. Например, все программы из классическогоописания С [8] являются программами на С++. В процессе изучения С++ будетполезен опыт работы с любым языком со статическими типами. Эффективность и структура Развитие языка С++ происходило на базе языка С, и, за небольшимисключением, С был сохранен в качестве подмножества C++. Базовый язык Сбыл спроектирован таким образом, что имеется очень тесная связь междутипами, операциями, операторами и объектами, с которыми непосредственноработает машина, т.е. числами, символами и адресами. За исключениемопераций new, delete и throw, а также проверяемого блока, для выполненияоператоров и выражений С++ не требуется скрытой динамической аппаратнойили программной поддержки. В С++ используется та же (или даже более эффективная)последовательность команд для вызова функций и возврата из них, что и в С.Если даже эти довольно эффективные операции становятся слишком дорогими,то вызов функции может быть заменен подстановкой ее тела, причемсохраняется удобная функциональная запись безо всяких расходов на вызовфункции. Первоначально язык С задумывался как конкурент ассемблера, способныйвытеснить его из основных и наиболее требовательных к ресурсам задачсистемного программирования. В проекте С++ были приняты меры, чтобы успехиС в этой области не оказались под угрозой. Различие между двумя языкамипрежде все состоит в степени внимания, уделяемого типам и структурам. ЯзыкС выразителен и в то же время снисходителен по отношению к типам. Язык С++еще более выразителен, но такой выразительности можно достичь лишь тогда,когда типам уделяют большое внимание. Когда типы объектов известны,транслятор правильно распознает такие выражения, в которых иначепрограммисту пришлось бы записывать операции с утомительнымиподробностями. Кроме того, знание типов позволяет трансляторуобнаруживать такие ошибки, которые в противном случае были бы выявленытолько при тестировании. Отметим, что само по себе использование строгойтипизации языка для контроля параметров функции, защиты данных отнезаконного доступа, определения новых типов и операций не влечетдополнительных расходов памяти и увеличения времени выполнения программы. В проекте С++ особое внимание уделяется структурированию программы.Это вызвано увеличением размеров программ со времени появления С.Небольшую программу (скажем, не более 1000 строк) можно заставить изупрямства работать, нарушая все правила хорошего стиля программирования.Однако, действуя так, человек уже не сможет справиться с большойпрограммой. Если у вашей программы в 10 000 строк плохая структура, то выобнаружите, что новые ошибки появляются в ней так же быстро, как удаляютсястарые. С++ создавался с целью, чтобы большую программу можно былоструктурировать таким образом, чтобы одному человеку не пришлось работатьс текстом в 25000 строк. В настоящее время можно считать, что эта цельполностью достигнута. Существуют, конечно, программы еще большего размера. Однако те из них,которые действительно используются, обычно можно разбить на несколькопрактически независимых частей, каждая из которых имеет значительноменьший упомянутого размер. Естественно, трудность написания исопровождения программы определяется не только числом строк текста, но исложностью предметной области. Так что приведенные здесь числа, которымиобосновывались наши соображения, не надо воспринимать слишком серьезно. К сожалению, не всякую часть программы можно хорошо структурировать,сделать независимой от аппаратуры, достаточно понятной и т.д. В С++ естьсредства, непосредственно и эффективно представляющие аппаратныевозможности. Их использование позволяет избавиться от беспокойства онадежности и простоте понимания программы. Такие части программы можноскрывать, предоставляя надежный и простой интерфейс с ними. Естественно, если С++ используется для большой программы, то этоозначает, что язык используют группы программистов. Полезную роль здесьсыграют свойственные языку модульность, гибкость и строго типизированныеинтерфейсы. В С++ есть такой же хороший набор средств для создания большихпрограмм, как во многих языках. Но когда программа становится еще больше,проблемы по ее созданию и сопровождению перемещаются из области языка вболее глобальную область программных средств и управления проектом. Этимвопросам посвящены главы 11 и 12. В этой книге основное внимание уделяется методам созданияуниверсальных средств, полезных типов, библиотек и т.д. Эти методы можноуспешно применять как для маленьких, так и для больших программ. Болеетого, поскольку все нетривиальные программы состоят из нескольких взначительной степени независимых друг от друга частей, методыпрограммирования отдельных частей пригодятся как системным, так иприкладным программистам. Может возникнуть подозрение, что запись программы с использованиемподробной системы типов, увеличит размер текста. Для программы на С++ этоне так: программа на С++, в которой описаны типы формальных параметровфункций, определены классы и т.п., обычно бывает даже короче своегоэквивалента на С, где эти средства не используются. Когда в программе наС++ используются библиотеки, она также оказывается короче своегоэквивалента на С, если, конечно, он существует. Философские замечания Язык программирования решает две взаимосвязанные задачи: позволяетпрограммисту записать подлежащие выполнению действия и формирует понятия,которыми программист оперирует, размышляя о своей задаче. Первой целиидеально отвечает язык, который очень "близок машине". Тогда со всеми ееосновными "сущностями" можно просто и эффективно работать на этом языке,причем делая это очевидным для программиста способом. Именно это имели ввиду создатели С. Второй цели идеально отвечает язык, который настолько"близок к поставленной задаче", что на нем непосредственно и точновыражаются понятия, используемые в решении задачи. Именно это имелось ввиду, когда первоначально определялись средства, добавляемые к С. Связь между языком, на котором мы думаем и программируем, а такжемежду задачами и их решениями, которые можно представить в своемвоображении, довольно близка. По этой причине ограничивать возможностиязыка только поиском ошибок программиста - в лучшем случае опасно. Как ив случае естественных языков, очень полезно обладать, по крайней мере,двуязычием. Язык предоставляет программисту некоторые понятия в видеязыковых инструментов; если они не подходят для задачи, их простоигнорируют. Например, если существенно ограничить понятие указателя, топрограммист будет вынужден для создания структур, указателей и т.п.использовать вектора и операции с целыми. Хороший проект программы иотсутствие в ней ошибок нельзя гарантировать только наличием илиотсутствием определенных возможностей в языке. Типизация языка должна быть особенно полезна для нетривиальных задач.Действительно, понятие класса в С++ проявило себя как мощноеконцептуальное средство. Замечания о программировании на языке С++ Предполагается, что в идеальном случае разработка программы делится натри этапа: вначале необходимо добиться ясного понимания задачи, затемопределить ключевые понятия, используемые для ее решения, и, наконец,полученное решение выразить в виде программы. Однако, детали решения иточные понятия, которые будут использоваться в нем, часто проясняютсятолько после того, как их попытаются выразить в программе. Именно в этомслучае большое значение приобретает выбор языка программирования. Во многих задачах используются понятия, которые трудно представить впрограмме в виде одного из основных типов или в виде функции без связанныхс ней статических данных. Такое понятие может представлять в программекласс. Класс - это тип; он определяет поведение связанных с ним объектов:их создание, обработку и уничтожение. Кроме этого, класс определяетреализацию объектов в языке, но на начальных стадиях разработки программыэто не является и не должно являться главной заботой. Для написанияхорошей программы надо составить такой набор классов, в котором каждыйкласс четко представляет одно понятие. Обычно это означает, чтопрограммист должен сосредоточиться на вопросах: Как создаются объектыданного класса? Могут ли они копироваться и (или) уничтожаться? Какиеоперации можно определить над этими объектами? Если на эти вопросыудовлетворительных ответов не находится, то, скорее всего, это означает,что понятие не было достаточно ясно сформулировано. Тогда, возможно,стоит еще поразмышлять над задачей и предлагаемым решением, а ненемедленно приступать к программированию, надеясь в процессе него найтиответы. Проще всего работать с понятиями, которые имеют традиционнуюматематическую форму представления: всевозможные числа, множества,геометрические фигуры и т.д. Для таких понятий полезно было бы иметьстандартные библиотеки классов, но к моменту написания книги их еще небыло. В программном мире накоплено удивительное богатство из такихбиблиотек, но нет ни формального, ни фактического стандарта на них. ЯзыкС++ еще достаточно молод, и его библиотеки не развились в такой степени,как сам язык. Понятие не существует в вакууме, вокруг него всегда группируютсясвязанные с ним понятия. Определить в программе взаимоотношения классов,иными словами, установить точные связи между используемыми в задачепонятиями, бывает труднее, чем определить каждый из классов сам по себе. Врезультате не должно получиться "каши" - когда каждый класс (понятие)зависит от всех остальных. Пусть есть два класса A и B. Тогда связи междуними типа "A вызывает функцию из B", "A создает объекты B", "A имеет члентипа B" обычно не вызывают каких-либо трудностей. Связи же типа "Aиспользует данные из B", как правило, можно вообще исключить. Одно из самых мощных интеллектуальных средств, позволяющих справитьсясо сложностью, - это иерархическое упорядочение, т.е. упорядочениесвязанных между собой понятий в древовидную структуру, в которой самоеобщее понятие находится в корне дерева. Часто удается организовать классыпрограммы как множество деревьев или как направленный ацикличный граф. Этоозначает, что программист определяет набор базовых классов, каждый изкоторых имеет свое множество производных классов. Набор операций самогообщего вида для базовых классов (понятий) обычно определяется с помощьювиртуальных функций ($$6.5). Интерпретация этих операций, по меренадобности, может уточняться для каждого конкретного случая, т.е. длякаждого производного класса. Естественно, есть ограничения и при такой организации программы.Иногда используемые в программе понятия не удается упорядочить даже спомощью направленного ацикличного графа. Некоторые понятия оказываются посвоей природе взаимосвязанными. Циклические зависимости не вызовутпроблем, если множество взаимосвязанных классов настолько мало, что в немлегко разобраться. Для представления на С++ множества взаимозависимыхклассов можно использовать дружественные классы ($$5.4.1). Если понятия программы нельзя упорядочить в виде дерева илинаправленного ацикличного графа, а множество взаимозависимых понятий неподдается локализации, то, по всей видимости, вы попали в такоезатруднительное положение, выйти из которого не сможет помочь ни один изязыков программирования. Если вам не удалось достаточно простосформулировать связи между основными понятиями задачи, то, скорее всего,вам не удастся ее запрограммировать. Еще один способ выражения общности понятий в языке предоставляютшаблоны типа. Шаблонный класс задает целое семейство классов. Например,шаблонный класс список задает классы вида "список объектов T", где T можетбыть произвольным типом. Таким образом, шаблонный тип указывает, какполучается новый тип из заданного в качестве параметра. Самые типичныешаблонные классы - это контейнеры, в частности, списки, массивы иассоциативные массивы. Напомним, что можно легко и просто запрограммировать многие задачи,используя только простые типы, структуры данных, обычные функции инесколько классов из стандартных библиотек. Весь аппарат построения новыхтипов следует привлекать только тогда, когда он действительно необходим. Вопрос "Как написать хорошую программу на С++?" очень похож на вопрос"Как пишется хорошая английская проза?". На него есть два ответа: "Нужнознать, что вы, собственно, хотите написать" и "Практика и подражаниехорошему стилю". Оба совета пригодны для С++ в той же мере, что и дляанглийского языка, и обоим достаточно трудно следовать. Несколько полезных советов Ниже представлен "свод правил", который стоит учитывать при изученииС++. Когда вы станете более опытными, то на базе этих правил сможетесформулировать свои собственные, которые будут более подходить для вашихзадач и более соответствовать вашему стилю программирования. Сознательновыбраны очень простые правила, и в них опущены подробности. Не следуетвоспринимать их слишком буквально. Хорошая программа требует и ума, ивкуса, и терпения. С первого раза обычно она не получается, поэтомуэкспериментируйте! Итак, свод правил. [1] Когда вы пишите программу, то создаете конкретные представления тех понятий, которые использовались в решении поставленной задачи. Структура программы должна отражать эти понятия настолько явно, насколько это возможно. [a] Если вы считаете "нечто" отдельным понятием, то сделайте его классом. [b] Если вы считаете "нечто" существующим независимо, то сделайте его объектом некоторого класса. [c] Если два класса имеют нечто существенное, и оно является для них общим, то выразите эту общность с помощью базового класса. [d] Если класс является контейнером некоторых объектов, сделайте его шаблонным классом.[2] Если определяется класс, который не реализует математических объектов вроде матриц или комплексных чисел и не является типом низкого уровня наподобие связанного списка, то: [а] Не используйте глобальных данных. [b] Не используйте глобальных функций (не членов). [c] Не используйте общих данных-членов. [d] Не используйте функции friend (но только для того, чтобы избежать [а], [b] или [c]). [e] Не обращайтесь к данным-членам другого объекта непосредственно. [f] Не заводите в классе "поле типа"; используйте виртуальные функции. [g] Используйте функции-подстановки только как средство значительной оптимизации. Замечание для программистов на С Чем лучше программист знает С, тем труднее будет для него припрограммировании на С++ отойти от стиля программирования на С. Так онтеряет потенциальные преимущества С++. Поэтому советуем просмотреть раздел"Отличия от С" в справочном руководстве ($$R.18). Здесь мы только укажемна те места, в которых использование дополнительных возможностей С++приводит к лучшему решению, чем программирование на чистом С. Макрокомандыпрактически не нужны в С++: используйте const ($$2.5) или enum ($$2.5.1),чтобы определить поименованные константы; используйте inline ($$4.6.2),чтобы избежать расходов ресурсов, связанных с вызовом функций; используйтешаблоны типа ($$8), чтобы задать семейство функций и типов. Не описывайтепеременную, пока она действительно вам не понадобится, а тогда ее можносразу инициализировать, ведь в С++ описание может появляться в любомместе, где допустим оператор. Не используйте malloc(), эту операцию лучшереализует new ($$3.2.6). Объединения нужны не столь часто, как в С,поскольку альтернативность в структурах реализуется с помощью производныхклассов. Старайтесь обойтись без объединений, но если они все-таки нужны,не включайте их в основные интерфейсы; используйте безымянные объединения($$2.6.2). Старайтесь не использовать указателей типа void*,арифметических операций с указателями, массивов в стиле С и операцийприведения. Если все-таки вы используете эти конструкции, упрятывайте ихдостаточно надежно в какую-нибудь функцию или класс. Укажем, чтосвязывание в стиле С возможно для функции на С++, если она описана соспецификацией extern "C" ($$4.4). Но гораздо важнее стараться думать о программе как о множествевзаимосвязанных понятий, представляемых классами и объектами, чемпредставлять ее как сумму структур данных и функций, что-то делающих сэтими данными. Список литературы В книге немного непосредственных ссылок на литературу. Здесь приведенсписок книг и статей, на которые есть прямые ссылки, а также тех, которыетолько упоминаются. [1] A.V.Aho, J.E.Hopcroft, and J.D.Ulman: Data Structures andAlgoritms. Addison-Wesley, Reading, Massachusetts. 1983. [2] O-J.Dahl, B.Myrhaug, and K.Nugaard: SIMULA Common Base Language.Norwegian Computing Ctnter S-22. Oslo, Norway. 1970 [3] O-J.Dahl and C.A.R.Hoare: Hierarhical Program Construction inStructured Programming. Academic Press, New York. 1972. pp. 174-220. [4] Margaret A.Ellis and Bjarne Stroustrup: The Annotated C++Reference Manual. Addison-Wesley, Reading, Massachusetts. 1990. [5] A.Goldberg and D.Rodson: SMALLTALK-80 - The Language and ItsImplementation. Addison-Wesley, Reading, Massachusetts. 1983. [6] R.E.Griswold et.al.: The Snobol14 Programming Language.Prentice-Hall, Englewood Cliffs, New Jersy, 1970. [7] R.E.Griswold and M.T.Griswold: The ICON Programming Language.Prentice-Hall, Englewood Cliffs, New Jersy. 1983. [8] Brian W.Kernighan and Dennis M.Ritchie: The C ProgrammingLanguage. Prentice-Hall, Englewood Cliffs, New Jersy. 1978. Secondedition 1988. [9] Andrew Koenig and Bjarne Stroustrup: C++: As Close to C aspossible - but no closer. The C++ Report. Vol.1 No.7. July 1989. [10] Andrew Koenig and Bjarne Stroustrup: Exception Handling for C++(revised). Proc USENIX C++ Conference, April 1990. Also, Journal of ObjectOriented Programming, Vol.3 No.2, July/August 1990. pp.16-33. [11] Barbara Liskov et.al.: CLU Reference Manual. MIT/LCS/TR-225. [12] George Orwell: 1984. Secker and Warburg, London. 1949. [13] Martin Richards and Colin Whitby-Strevens: BCPL - The Languageand Its Compiler. Cambridge University Press. 1980. [14] L.Rosler: The Evolution of C - Past and Future. AT&T BellLaboratories Technical Journal. Vol.63 No.8 Part 2. October 1984.pp.1685-1700. [15] Ravi Sethi: Uniform Syntax for Type Expressions and Declarations.Software Practice & Experience, Vol.11. 1981. pp.623-628. [16] Bjarne Stroustrup: Adding Classes to C: An Exercise in LanguageEvolution. Software Practice & Experience, Vol.13. 1983. pp.139-61. [17] Bjarne Stroustrup: The C++ Programming Language. Addison-Wesley.1986. [18] Bjarne Stroustrup: Multiple Inheritance for C++. Proc. EUUGSpring Conference, May 1987. Also USENIX Computer Systems, Vol.2 No 4,Fall 1989. [19] Bjarne Stroustrup and Jonathan Shopiro: A Set of C classes forCo-Routine Style Programming. Proc. USENIX C++ conference, Santa


Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: