Бьерн Страуструп (Стpаустpуп - Книга о C++), страница 5
Описание файла
Документ из архива "Стpаустpуп - Книга о C++", который расположен в категории "". Всё это находится в предмете "информатика" из , которые можно найти в файловом архиве . Не смотря на прямую связь этого архива с , его также можно найти и в других разделах. Архив можно найти в разделе "книги и методические указания", в предмете "информатика" в общих файлах.
Онлайн просмотр документа "Бьерн Страуструп"
Текст 5 страницы из документа "Бьерн Страуструп"
[17] Bjarne Stroustrup: The C++ Programming Language. Addison-Wesley.
1986.
[18] Bjarne Stroustrup: Multiple Inheritance for C++. Proc. EUUG
Spring Conference, May 1987. Also USENIX Computer Systems, Vol.2 No 4,
Fall 1989.
[19] Bjarne Stroustrup and Jonathan Shopiro: A Set of C classes for
Co-Routine Style Programming. Proc. USENIX C++ conference, Santa Fe.
November 1987. pp.417-439.
[20] Bjarne Stroustrup: Type-safe Linkage for C++. USENIX Computer
Systems, Vol.1 No.4 Fall 1988.
[21] Bjurne Stroustrup: Parameterized Type for C++. Proc. USENIX C++
Conference, Denver, October 1988. pp.1-18. Also, USENIX Computer Systems,
Vol.2 No.1 Winter 1989.
[22] Bjarne Stroustrup: Standardizing C++. The C++ Report. Vol.1
No.1. January 1989.
[23] Bjarne Stroustrup: The Evolution of C++: 1985-1989. USENIX
Computer Systems, Vol.2 No.3. Summer 1989.
[24] P.M.Woodward and S.G.Bond: Algol 68-R Users Guide. Her Majesty's
Stationery Office, London. 1974.
[25] UNIX Time-Sharing System: Programmer's Manual. Research Version,
Tenth Edition. AT&T Bell Laboratories, Murray Hill, New Jersy, February
1985.
[26] Aake Wilkstroem: Functional Programming Using ML. Prentice-Hall,
Englewood Cliffs, New Jersy. 1987.
[27] X3 Secretariat: Standard - The C Language. X3J11/90-013.
Computer and Business Equipment Manufactures Association, 311 First
Street, NW, Suite 500, Washington, DC 20001, USA.
Ссылки на источники по проектированию и развитию больших систем
программного обеспечения можно найти в конце главы 11.
* КРАТКИЙ ОБЗОР С++
"Начнем с того, что вздернем
всех этих законников, языковедов".
("Король Генрих VI", действие II)
В этой главе содержится краткий обзор основных концепций и конструкций
языка С++. Он служит для беглого знакомства с языком. Подробное описание
возможностей языка и методов программирования на нем дается в следующих
главах. Разговор ведется в основном вокруг абстракции данных и
объектно-ориентированного программирования, но перечисляются и основные
возможности процедурного программирования.
1.1 ВВЕДЕНИЕ
Язык программирования С++ задумывался как язык, который будет:
- лучше языка С;
- поддерживать абстракцию данных;
- поддерживать объектно-ориентированное программирование.
В этой главе объясняется смысл этих фраз без подробного описания
конструкций языка.
$$1.2 содержит неформальное описание различий "процедурного",
"модульного" и "объектно-ориентированного" программирования. Приведены
конструкции языка, которые существенны для каждого из перечисленных стилей
программирования. Свойственный С стиль программирования обсуждается в
разделах "процедурное программирование и "модульное программирование".
Язык С++ - "лучший вариант С". Он лучше поддерживает такой стиль
программирования, чем сам С, причем это делается без потери какой-либо
общности или эффективности по сравнению с С. В то же время язык C
является подмножеством С++. Абстракция данных и объектно-ориентированное
программирование рассматриваются как "поддержка абстракции данных" и
"поддержка объектно- ориентированного программирования". Первая базируется
на возможности определять новые типы и работать с ними, а вторая - на
возможности задавать иерархию типов.
$$1.3 содержит описание основных конструкций для процедурного и
модульного программирования. В частности, определяются функции, указатели,
циклы, ввод-вывод и понятие программы как совокупности раздельно
транслируемых модулей. Подробно эти возможности описаны в главах 2, 3 и 4.
$$1.4 содержит описание средств, предназначенных для эффективной
реализации абстракции данных. В частности, определяются классы, простейший
механизм контроля доступа, конструкторы и деструкторы, перегрузка
операций, преобразования пользовательских типов, обработка особых ситуаций
и шаблоны типов. Подробно эти возможности описаны в главах 5, 7, 8 и 9.
$$1.5 содержит описание средств поддержки объектно-ориентированного
программирования. В частности, определяются производные классы и
виртуальные функции, обсуждаются некоторые вопросы реализации. Все это
подробно изложено в главе 6.
$$1.6 содержит описание определенных ограничений на пути
совершенствования как языков программирования общего назначения вообще,
так и С++ в частности. Эти ограничения связаны с эффективностью, с
противоречащими друг другу требованиями разных областей приложения,
проблемами обучения и необходимостью трансляции и выполнения программ в
старых системах.
Если какой-то раздел окажется для вас непонятным, настоятельно
советуем прочитать соответствующие главы, а затем, ознакомившись с
подробным описанием основных конструкций языка, вернуться к этой главе.
Она нужна для того, чтобы можно было составить общее представление о
языке. В ней недостаточно сведений, чтобы немедленно начать
программировать.
1.2 Парадигмы программирования
Объектно-ориентированное программирование - это метод
программирования, способ написания "хороших" программ для множества задач.
Если этот термин имеет какой-то смысл, то он должен подразумевать: такой
язык программирования, который предоставляет хорошие возможности для
объектно-ориентированного стиля программирования.
Здесь следует указать на важные различия. Говорят, что язык
поддерживает некоторый стиль программирования, если в нем есть такие
возможности, которые делают программирование в этом стиле удобным
(достаточно простым, надежным и эффективным). Язык не поддерживает
некоторый стиль программирования, если требуются большие усилия или даже
искусство, чтобы написать программу в этом стиле. Однако это не означает,
что язык запрещает писать программы в этом стиле. Действительно, можно
писать структурные программы на Фортране и объектно-ориентированные
программы на С, но это будет пустой тратой сил, поскольку данные языки не
поддерживают указанных стилей программирования.
Поддержка языком определенной парадигмы (стиля) программирования явно
проявляется в конкретных языковых конструкциях, рассчитанных на нее. Но
она может проявляться в более тонкой, скрытой форме, когда отклонение от
парадигмы диагностируется на стадии трансляции или выполнения программы.
Самый очевидный пример - это контроль типов. Кроме того, языковая
поддержка парадигмы может дополняться проверкой на однозначность и
динамическим контролем. Поддержка может предоставляться и помимо самого
языка, например, стандартными библиотеками или средой программирования.
Нельзя сказать, что один язык лучше другого только потому, что в нем
есть возможности, которые в другом отсутствуют. Часто бывает как раз
наоборот. Здесь более важно не то, какими возможностями обладает язык, а
то, насколько имеющиеся в нем возможности поддерживают избранный стиль
программирования для определенного круга задач. Поэтому можно
сформулировать следующие требования к языку:
[1] Все конструкции языка должны естественно и элегантно определяться
в нем.
[2] Для решения определенной задачи должна быть возможность
использовать сочетания конструкций, чтобы избежать необходимости вводить
для этой цели новую конструкцию.
[3] Должно быть минимальное число неочевидных конструкций специального
назначения.
[4] Конструкция должна допускать такую реализацию, чтобы в
неиспользующей ее программе не возникло дополнительных расходов.
[5] Пользователю достаточно знать только то множество конструкций,
которое непосредственно используется в его программе.
Первое требование апеллирует к логике и эстетическому вкусу. Два
следующих выражают принцип минимальности. Два последних можно иначе
сформулировать так: "то, чего вы не знаете, не сможет нанести вам вреда".
С учетом ограничений, указанных в этих правилах, язык С++
проектировался для поддержки абстракции данных и объектно-ориентированного
программирования в добавление к традиционному стилю С. Впрочем, это не
значит, что язык требует какого-то одного стиля программирования от всех
пользователей.
Теперь перейдем к конкретным стилям программирования и посмотрим
каковы основные конструкции языка, их поддерживающие. Мы не собираемся
давать полное описание этих конструкций.
1.2.1 Процедурное программирование
Первоначальной (и, возможно, наиболее используемой) парадигмой
программирования было:
Определите, какие процедуры вам нужны; используйте лучшие из известных
вам алгоритмов!
Ударение делалось на обработку данных с помощью алгоритма,
производящего нужные вычисления. Для поддержки этой парадигмы языки
предоставляли механизм передачи параметров и получения результатов
функций. Литература, отражающая такой подход, заполнена рассуждениями о
способах передачи параметров, о том, как различать параметры разных типов,
о различных видах функций (процедуры, подпрограммы, макрокоманды, ...) и
т.д. Первым процедурным языком был Фортран, а Алгол60, Алгол68, Паскаль и
С продолжили это направление.
Типичным примером хорошего стиля в таком понимании может служить
функция извлечения квадратного корня. Для заданного параметра она выдает
результат, который получается с помощью понятных математических операций:
double sqrt ( double arg )
{
// программа для вычисления квадратного корня
}
voide some_function ()
{
double root = sqrt ( 2 );
// ..
}
Двойная наклонная черта // начинает комментарий, который продолжается
до конца строки.
При такой организации программы функции вносят определенный порядок в
хаос различных алгоритмов.
1.2.2 Модульное программирование
Со временем при в проектировании программ акцент сместился с
организации процедур на организацию структур данных. Помимо всего прочего
это вызвано и ростом размеров программ. Модулем обычно называют
совокупность связанных процедур и тех данных, которыми они управляют.
Парадигма программирования приобрела вид:
Определите, какие модули нужны; поделите программу так, чтобы данные
были скрыты в этих модулях
Эта парадигма известна также как "принцип сокрытия данных". Если в
языке нет возможности сгруппировать связанные процедуры вместе с данными,
то он плохо поддерживает модульный стиль программирования. Теперь метод
написания "хороших" процедур применяется для отдельных процедур модуля.
Типичный пример модуля - определение стека. Здесь необходимо решить такие
задачи:
[1] Предоставить пользователю интерфейс для стека (например, функции
push () и pop ()).
[2] Гарантировать, что представление стека (например, в виде массива
элементов) будет доступно лишь через интерфейс пользователя.
[3] Обеспечивать инициализацию стека перед первым его использованием.
Язык Модула-2 прямо поддерживает эту парадигму, тогда как С только
допускает такой стиль. Ниже представлен на С возможный внешний интерфейс
модуля, реализующего стек:
// описание интерфейса для модуля,
// реализующего стек символов:
void push ( char );
char pop ();
const int stack_size = 100;
Допустим, что описание интерфейса находится в файле stack.h, тогда
реализацию стека можно определить следующим образом:
#include "stack.h" // используем интерфейс стека
static char v [ stack_size ]; // ``static'' означает локальный
// в данном файле/модуле
static char * p = v; // стек вначале пуст
void push ( char c )
{
//проверить на переполнение и поместить в стек
}
char pop ()
{
//проверить, не пуст ли стек, и считать из него
}
Вполне возможно, что реализация стека может измениться, например, если
использовать для хранения связанный список. Пользователь в любом случае не
имеет непосредственного доступа к реализации: v и p - статические
переменные, т.е. переменные локальные в том модуле (файле), в котором они
описаны. Использовать стек можно так:
#include "stack.h" // используем интерфейс стека
void some_function ()
{
push ( 'c' );
char c = pop ();
if ( c != 'c' ) error ( "невозможно" );
}