Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
c++book1.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
1.83 Mб
Скачать

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

Язык программирования служит двум связанным между собой целям: он дает программисту аппарат для задания действий, ко­торые должны быть выполнены, и формирует концепции, которыми пользуется программист, размышляя о том, что делать. Первой цели идеально отвечает язык, который настолько "близок к ма­шине", что всеми основными машинными аспектами можно легко и просто оперировать достаточно очевидным для программиста об­разом. С таким умыслом первоначально задумывался 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).

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

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

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]