Сообщений 7    Оценка 142        Оценить  
Система Orphus

Дизайн и эволюция C++

Автор: Бьерн Страуструп
Издательство: Питер, 2006
448 страницы

Материал предоставил: Издательство ''Питер''
Найти в магазинах
Купить в Озоне (425 руб.)
Купить в Books.Ru
Купить в Болеро (339 руб.)
Купить в издательстве "Питер"
Купить в My-Shop.ru (343 руб.)

Аннотация

Содержание
Предисловие
Глава 1. Предыстория C++
1.1. Язык Simula и распределенные системы
1.2. Язык C и системное программирование
1.3. Немного об авторе книги

Аннотация

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

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

Содержание

Предисловие
Благодарности
Обращение к читателю

Часть I

Глава 1. Предыстория C++

1.1. Язык Simula и распределенные системы
1.2. Язык C и системное программирование
1.3. Немного об авторе книги

Глава 2. Язык С with Classes

2.1. Рождение C with Classes
2.2. Обзор языковых возможностей
2.3. Классы
2.4. Эффективность исполнения
2.4.1. Встраивание
2.5. Модель компоновки
2.5.1. Простые реализации
2.5.2. Модель размещения объекта в памяти
2.6. Статический контроль типов
2.6.1. Сужающие преобразования
2.6.2. О пользе предупреждений
2.7. Почему C?
2.8. Проблемы синтаксиса
2.8.1. Синтаксис объявлений в языке C
2.8.2. Тэги структур и имена типов
2.8.3. Важность синтаксиса
2.9. Производные классы
2.9.1. Полиморфизм без виртуальных функций
2.9.2. Контейнерные классы без шаблонов
2.9.3. Модель размещения объекта в памяти
2.9.4. Ретроспектива
2.10. Модель защиты
2.11. Гарантии времени исполнения
2.11.1. Конструкторы и деструкторы
2.11.2. Распределение памяти и конструкторы
2.11.3. Функции call и return
2.12. Менее существенные средства
2.12.1. Перегрузка оператора присваивания
2.12.2. Аргументы по умолчанию
2.13. Что не реализовано в C with Classes
2.14. Рабочая обстановка

Глава 3. Рождение С++

3.1. От C with Classes к C++
3.2. Цели С++
3.3. Компилятор Cfront
3.3.1. Генерирование С-кода
3.3.2. Синтаксический анализ C++
3.3.3. Проблемы компоновки
3.3.4. Версии Cfront
3.4. Возможности языка
3.5. Виртуальные функции
3.5.1. Модель размещения объекта в памяти
3.5.2. Замещение и поиск подходящей виртуальной функции
3.5.3. Сокрытие членов базового класса
3.6. Перегрузка
3.6.1. Основы перегрузки
3.6.2. Функции-члены и дружественные функции
3.6.3. Операторные функции
3.6.4. Перегрузка и эффективность
3.6.5. Изменение языка и новые операторы
3.7. Ссылки
3.7.1. Lvalue и Rvalue
3.8. Константы
3.9. Управление памятью
3.10. Контроль типов
3.11. Второстепенные возможности
3.11.1. Комментарии
3.11.2. Нотация для конструкторов
3.11.3. Квалификация
3.11.4. Инициализация глобальных объектов
3.11.5. Предложения объявления
3.12. Языки C и C++
3.13. Инструменты для проектирования языка
3.14. Книга ''Язык программирования С++''
3.15. Статья ''Whatis?''

Глава 4. Правила проектирования языка C++

4.1. Правила и принципы
4.2. Общие правила
4.3. Правила поддержки проектирования
4.4. Технические правила
4.5. Правила поддержки низкоуровневого программирования 2
4.6. Заключительное слово

Глава 5. Хронология 1985-1993 гг.

5.1. Введение
5.2. Версия 2.0
5.2.1. Обзор возможностей
5.3. Аннотированное справочное руководство
5.3.1. Обзор ARM
5.4. Стандартизация ANSI и ISO
5.4.1. Обзор возможностей

Глава 6. Стандартизация

6.1. Что такое стандарт?
6.1.1. Детали реализации
6.1.2. Тест на реалистичность
6.2. Работа комитета
6.2.1. Кто работает в комитете
6.3. Как велась работа
6.3.1. Разрешение имен
6.3.2. Время жизни объектов
6.4. Расширения
6.4.1. Критерии рассмотрения предложений
6.4.2. Текущее состояние дел
6.4.3. Проблемы, связанные с полезными расширениями
6.4.4. Логическая непротиворечивость
6.5. Примеры предлагавшихся расширений
6.5.1. Именованные аргументы
6.5.2. Ограниченные указатели
6.5.3. Наборы символов

Глава 7. Заинтересованность и использование

7.1. Рост интереса к C++
7.1.1. Отсутствие маркетинга C++
7.1.2. Конференции
7.1.3. Журналы и книги
7.1.4. Компиляторы
7.1.5. Инструментальные средства и среды программирования
7.2. Преподавание и изучение C++
7.3. Пользователи и приложения
7.3.1. Первые пользователи
7.3.2. Сферы применения C++
7.4. Коммерческая конкуренция
7.4.1. Традиционные языки
7.4.2. Современные языки
7.4.3. Как выдержать конкуренцию

Глава 8. Библиотеки

8.1. Введение
8.2. Проектирование библиотеки C++
8.2.1. Альтернативы при проектировании библиотеки
8.2.2. Языковые средства и построение библиотеки
8.2.3. Как работать с разнообразными библиотеками
8.3. Ранние библиотеки
8.3.1. Библиотека потокового ввода/вывода
8.3.2. Поддержка параллельности
8.4. Другие библиотеки
8.4.1. Базовые библиотеки
8.4.2. Устойчивость и базы данных
8.4.3. Библиотеки для численных расчетов
8.4.4. Специализированные библиотеки
8.5. Стандартная библиотека

Глава 9. Перспективы развития языка С++

9.1. Введение
9.2. Оценка пройденного пути
9.2.1. Достигнуты ли основные цели C++?
9.2.2. Является ли C++ логически последовательным языком?
9.2.3. Основная недоработка языка
9.3. Всего лишь мост?
9.3.1. Мост нужен надолго
9.3.2. Если C++ - это ответ, то на какой вопрос?
9.4. Что может сделать C++ более эффективным
9.4.1. Стабильность и стандарты
9.4.2. Обучение и приемы
9.4.3. Системные вопросы
9.4.4. За пределами файлов и синтаксиса
9.4.5. Подведение итогов и перспективы

Часть II

Глава 10. Управление памятью

10.1. Введение
10.2. Отделение распределения памяти и инициализации
10.3. Выделение памяти для массива
10.4. Размещение объекта в памяти
10.5. Проблемы освобождения памяти
10.5.1. Освобождение памяти для массивов
10.6. Нехватка памяти
10.7. Автоматическая сборка мусора
10.7.1. Необязательный сборщик мусора
10.7.2. Как должен выглядеть необязательный сборщик мусора?

Глава 11. Перегрузка

11.1. Введение
11.2. Разрешение перегрузки
11.2.1. Детальное разрешение
11.2.2. Управление неоднозначностью
11.2.3. Нулевой указатель
11.2.4. Ключевое слово overload
11.3. Типобезопасная компоновка
11.3.1. Перегрузка и компоновка
11.3.2. Реализация компоновки в C++
11.3.3. Анализ пройденного пути
11.4. Создание и копирование объектов
11.4.1. Контроль допустимости копирования
11.4.2. Управление распределением памяти
11.4.3. Управление наследованием
11.4.4. Почленное копирование
11.5. Удобство нотации
11.5.1. ''Умные'' указатели
11.5.2. ''Умные'' ссылки
11.5.3. Перегрузка операторов инкремента и декремента
11.5.4. Перегрузка ->*
11.5.5. Перегрузка оператора ''запятая''
11.6. Добавление в C++ операторов
11.6.1. Оператор возведения в степень
11.6.2. Операторы, определяемые пользователем
11.6.3. Составные операторы
11.7. Перечисления
11.7.1 Перегрузка на базе перечислений
11.7.2. Тип Boolean

Глава 12. Множественное наследование

12.1. Введение
12.2. Базовые классы
12.3. Виртуальные базовые классы
12.3.1. Виртуальные базовые классы и виртуальные функции
12.4. Модель размещения объекта в памяти
12.4.1. Размещение в памяти объекта виртуального базового класса
12.4.2. Виртуальные базовые классы и приведение типов
12.5. Комбинирование методов
12.6. Полемика о множественном наследовании
12.7. Делегирование
12.8. Переименование
12.9. Инициализаторы членов и базовых классов

Глава 13. Уточнения понятия класса

13.1 Введение
13.2. Абстрактные классы
13.2.1. Абстрактные классы и обработка ошибок
13.2.2. Абстрактные типы
13.2.3. Синтаксис
13.2.4. Виртуальные функции и конструкторы
13.3. Константные функции-члены
13.3.1. Игнорирование const при приведении типов
13.3.2. Уточнение определения const
13.3.3. Ключевое слово mutable и приведение типов
13.4. Статические функции-члены
13.5. Вложенные классы
13.6. Ключевое слово inherited
13.7. Ослабление правил замещения
13.7.1. Ослабление правил аргументов
13.8. Мультиметоды
13.8.1. Когда нет мультиметодов
13.9. Защищенные члены
13.10. Улучшенная генерация кода
13.11. Указатели на функции-члены

Глава 14. Приведение типов

14.1. Крупные расширения
14.2. Идентификация типа во время исполнения
14.2.1. Зачем нужен механизм RTTI
14.2.2. Оператор dynamic_cast
14.2.3. Правильное и неправильное использование RTTI
14.2.4. Зачем давать ''опасные средства''
14.2.5. Оператор typeid()
14.2.6. Модель размещения объекта в памяти
14.2.7. Простой ввод/вывод объектов
14.2.8. Другие варианты
14.3. Новая нотация для приведения типов
14.3.1. Недостатки старых приведений типов
14.3.2. Оператор static_cast
14.3.3. Оператор reinterpret_cast
14.3.4. Оператор const_cast
14.3.5. Преимущества новых приведений типов

Глава 15. Шаблоны

15.1. Введение
15.2. Зачем нужны шаблоны
15.3. Шаблоны классов
15.3.1. Аргументы шаблонов, не являющиеся типами
15.4. Ограничения на аргументы шаблонов
15.4.1. Ограничения за счет наследования
15.4.2. Ограничения за счет использования
15.5. Устранение дублирования кода
15.6. Шаблоны функций
15.6.1. Выведение аргументов шаблона функции
15.6.2. Задание аргументов шаблона функции
15.6.3. Перегрузка шаблона функции
15.7. Синтаксис
15.8. Методы композиции
15.8.1. Представление стратегии реализации
15.8.2. Представление отношений порядка
15.9. Соотношения между шаблонами классов
15.9.1. Отношения наследования
15.9.2. Преобразования
15.9.3. Шаблоны-члены
15.10. Инстанцирование шаблонов
15.10.1. Явное инстанцирование
15.10.2. Точка инстанцирования
15.10.3. Специализация
15.10.4. Нахождение определений шаблонов
15.11. Последствия введения шаблонов
15.11.1. Отделение реализации от интерфейса
15.11.2. Гибкость и эффективность
15.11.3. Влияние на другие компоненты C++

Глава 16. Обработка исключений

16.1. Введение
16.2. Цели и предположения
16.3. Синтаксис
16.4. Группировка
16.5. Управление ресурсами
16.5.1. Ошибки в конструкторах
16.6. Возобновление или завершение?
16.6.1. Обходные пути для реализации возобновления
16.7. Асинхронные события
16.8. Распространение на несколько уровней
16.9. Статическая проверка
16.9.1. Вопросы реализации
16.10. Инварианты

Глава 17. Пространства имен

17.1. Введение
17.2. Для чего нужны пространства имен
17.2.1. Обходные пути
17.3. Какое решение было бы лучшим?
17.4. Решение: пространства имен
17.4.1. Мнения по поводу пространств имен
17.4.2. Внедрение пространств имен
17.4.3. Псевдонимы пространства имен
17.4.4. Использование пространств имен для управления версиями
17.4.5. Технические детали
17.5. Классы и пространства имен
17.5.1. Производные классы
17.5.2. Использование базовых классов
17.5.3. Исключение глобальных статических объявлений
17.6. Совместимость с C

Глава 18. Препроцессор C

Алфавитный указатель

Предисловие

Кто не пашет, должен писать.
Мартин А. Хансен

На второй конференции ACM по истории языков программирования (HOPL2) меня попросили написать статью по истории C++. Мысль показалась мне разумной, предложение - лестным, поэтому я приступил к работе. Чтобы работа получилась более полной и неискаженной, я обратился за помощью к друзьям. Вслед за этим молва разнесла известие о готовящемся проекте. Не обошлось без преувеличений - и однажды я получил по электронной почте письмо с вопросом, где можно купить мою новую книгу о дизайне C++. Оно и положило начало этой серьезной работе.

Обычно в книгах по программированию и его языкам объясняется, чтo представляет собой язык и как им пользоваться. Но многих интересует вопрос, почему язык оказался именно таким и как он создавался. Именно об этом, применительно к C++, и говорится в данной книге. В ней рассказывается, как шла эволюция языка от первоначального проекта до нынешнего состояния, объясняются основные задачи и цели проектирования, заложенные в языке идеи и ограничения, описывается развитие языковых концепций. Естественно, ни C++, ни представления о его дизайне и применении не изменялись сами собой. В действительности эволюционировали сознание пользователей и их представления о том, какие перед ними стоят цели и какие инструменты необходимы для решения. А значит, в книге говорится о наиболее важных вопросах, которые снимались с помощью C++, а также о людях, решавших эти задачи и оказавших влияние на развитие языка, и их воззрениях.

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

Основное внимание в книге уделено общим целям дизайна, практическим ограничениям. Ключевые проектные решения, относящиеся к языковым средствам, излагаются в историческом контексте. Я прослеживаю эволюцию языка от C with Classes (C с классами) к версиям 1.0 и 2.0 и далее к проводимой в настоящее время комитетом ANSI/ISO работе по стандартизации. В книге анализируютсяи такие аспекты: резкое увеличение количества приложений по C++, возросший интерес пользователей к языку, усиление коммерческой активности, появление большого количества компиляторов, инструментальных средств, сред программирования и библиотек. Подробно обсуждаются связи между языками C++ и Simula.

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

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

Глава 1. Предыстория C++

Давнымдавно, когда правило Зло!
Кристен Найгаард

1.1. Язык Simula и распределенные системы

Предыстория C++ - за пару лет до того, как мне пришла в голову мысль добавить к C некоторые возможности из Simula, - важна потому, что в это время выкристаллизовались критерии, позднее положенные в основу C++. Я работал над докторской диссертацией в лаборатории вычислительной техники Кембриджского университета в Англии. Тема - изучение альтернативных способов построения распределенных систем. Работа велась на базе Кембриджского компьютера CAPс его экспериментальной и постоянно эволюционирующей операционной системой [Wilkes, 1979]. Подробности этой работы и ее результаты [Stroustrup, 1979] к C++ отношения не имеют. Существенными оказались интерес к построению программного обеспечения из четко определенных модулей и тот факт, что основным средством для экспериментирования стал большой симулятор, который я написал для моделирования работы программ в распределенной системе.

Первая версия симулятора была написана на Simula [Birtwistle, 1979] и работала на компьютере IBM 360/165, установленном в вычислительном центре Кембриджского университета. Возможности Simula почти идеально подходили для моих целей. Особенно поразил тот факт, что концепции языка помогали мне размышлять над существом своей задачи. Концепция класса позволила отобразить понятия из предметной области на языковые конструкции настолько естествен но, что мой код оказался понятнее, чем все, что я видел в других языках. То, что классы Simula могли использоваться в качестве сопрограмм, позволило мне легко выразить параллельность, присущую моему приложению. Например, объект класса computer было совсем просто заставить работать псевдопараллельно с други ми объектами того же класса. Варианты понятий прикладного уровня выражались через иерархию классов. Так, виды компьютеров можно было представить как классы, производные от computer, а типы механизмов межмодульных коммуникаций - как классы, производные от класса IPC. Правда, этот прием я применял нечасто: для моего симулятора важнее было использовать классы с целью представления параллельности.

Во время написания и начальной отладки программы я смог в полной мере оценить выразительную мощь системы типов в Simula и способность компилятора находить ошибки типизации. Я заметил, что ошибки эти почти всегда являлись свидетельством невнимательности или изъяна проектирования. Последнее было важнее всего и помогало мне больше, чем примитивные сильно типизированные языки, с которыми доводилось работать раньше. Так я пришел к уже звучавшему выше выводу, что система типов в языке Pascal не просто бесполезна - это смирительная рубашка, которая создает больше проблем, нежели решает, заставляя меня жертвовать чистотой дизайна ради удовлетворения причуд компилятора.

Обнаруженный контраст между строгостью Pascal и гибкостью Simula оказался чрезвычайно важен при разработке C++. Концепция классов в Simula представлялась мне ключевым фактором, и с той поры я считаю, что при проектировании программ следует сосредотачивать свое внимание именно на классах. Я работал с Simula и прежде (во время учебы в университете города Аархус в Дании), но был приятно удивлен следующим: чем больше программа, тем очевидней польза от возможностей Simula. Механизмы классов и сопрограмм, а также исчерпывающий контроль типов гарантировали, что число ошибок увеличивается с ростом программы не более чем линейно (что было неожиданно). Напротив, программа работала, скорее, как набор очень маленьких программок, нежели как большой монолит, и поэтому писать, понимать и отлаживать ее было проще.

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

В то время я пришел к выводу, что реализация Simula (в отличие от самого языка) была ориентирована на небольшие по объему программы, а для больших не приспособлена [Stroustrup, 1979]. На связывание отдельно скомпилированных классов уходила масса времени: на компиляцию 1/30 части программы и связывание ее с остальными, уже откомпилированными модулями тратилось больше времени, чем на компиляцию и связывание всей программы как монолита. Думаю, что, вероятнее всего, это была проблема используемого компоновщика, а не самого языка Simula, но это слабое утешение. Кроме того, производительность программы была такой низкой, что не оставляла надежд получить от симулятора хоть сколько-нибудь полезные данные. Плохие показатели производительности были обусловлены языком и его реализацией, а не приложением. Проблема накладных расходов является в Simula фундаментальной и неустранимой. Она коренится в некоторых особенностях языка и их взаимодействиях: проверке типов во время исполнения, гарантированной инициализации переменных, поддержке параллельности, сборке мусора для объектов, созданных пользователем, и записей активации процедур.

Измерения показали: более 80% времени тратится на сборку мусора, хотя управление ресурсами брала на себя моделируемая система, так что мусор вообще не появлялся. Современные реализации Simula (15 лет спустя) стали лучше, но, по моим сведениям, увеличения производительности на порядок так и не достигнуто.

Чтобы не бросать проект, я переписал симулятор на BCPL и запускал его на экспериментальном компьютере CAP. Опыт кодирования и отладки на BCPL [Richards, 1980] оставил у меня неприятные воспоминания. Язык C по сравнению с BCPL - язык очень высокого уровня. Ни контроля типов, ни поддержки во время исполнения в BCPL здесь нет и в помине. Однако получившийся симулятор работал достаточно быстро и с его помощью я получил целый ряд полезных результатов. Они прояснили многие вопросы и легли в основу нескольких статей по операционным системам [Stroustrup, 1978, 1979b, 1981].

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

Эти критерии еще не были четко сформулированы, когда я покидал Кембридж. Некоторые из них окончательно оформились лишь в ходе последующего осмысления собственного опыта, приобретенного при создании симулятора и программ, которые я писал в течение еще пары лет, а также опыта других людей. C++ в том виде, какой он принял к моменту выхода версии 2.0, полностью отвечает данным критериям; серьезные проблемы, с которыми я столкнулся при проектировании шаблонов и обработке исключений, связаны с отходом от некоторых из этих принципов. Я полагаю, что самой важной особенностью сформулированных выше правил является их слабая связь с нюансами конкретных языков програм мирования. Вместо этого они налагают определенные ограничения на решение.

Когда я работал в Кембридже, лабораторию вычислительной техники возглавлял Морис Уилкс (Maurice Wilkes). Помощь во всех технических вопросах мне оказывали мой руководитель Дэвид Уилер (David Wheeler) и Роджер Нидэм (Roger Needham). Мои знания в области операционных систем и интерес к модульности и межмодульным коммуникациям способствовали развитию C++.

Например, модель защиты в C++ базируется на концепции предоставления и передачи прав доступа; различие между инициализацией и присваиванием возникло благодаря размышлениям о способности переноса (transferring capabilities); концепция const берет начало от механизмов защиты от чтения/записи в аппаратных устройствах; механизм обработки исключений появился в связи с работой над отказоустойчивыми системами, выполненной группой под руководством Брайана Рэнделла (Brian Randell) в Ньюкасле в 70х гг.

1.2. Язык C и системное программирование

На языке C я начал работать в Лондоне в 1975 г. и оценил его преимущества по сравнению с другими языками, которые принято называть языками для системного программирования, машинноориентированными или низкоуровневыми.

Из таких языков мне были известны PL 360, Coral, Mary и другие, но в основном BCPL. Я не только пользовался BCPL, но однажды и реализовал его путем трансляции в промежуточный микрокод - Oкод, так что хорошо представлял себе низкоуровневые аспекты, связанные с эффективностью языков такого класса.

Защитив диссертацию в Кембридже и получив работу в Bell Labs, я еще раз изучил C по книге Кернигана [Kernighan, 1978]. В то время я не был экспертом по C и рассматривал его в основном как самый современный и известный пример языка системного программирования. Лишь позже, приобретая собственный опыт и беседуя с коллегами - Стью Фельдманом (Stu Feldman), Стивом Джонсоном (Steve Johnson), Брайаном Керниганом и Деннисом Ричи, - я начал понастоящему понимать C. Таким образом, общее представление о языках системного программирования значило для формирования C++ по меньшей мере столько же, сколько конкретные технические детали C.

Я довольно хорошо знал Algol68 [Woodward,1974] по работе над небольшими проектами в Кембридже и видел связь между конструкциями этого языка и C. Иногда мне казалось полезным рассматривать конструкции С как частные случаи более общих конструкций Algol68. Любопытно, что я никогда не рассматривал Algol68 в качестве языка системного программирования (несмотря на то что сам пользовался написанной на нем операционной системой). Подозреваю, причина здесь в том, что я считал очень важными переносимость, простоту связывания с программами на других языках и эффективность исполнения. Как-то раз я сказал, что Algol68 с классами, как в Simula, - это язык моей мечты. Однако в качестве практического инструмента C казался мне лучше, чем Algol68.

1.3. Немного об авторе книги

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

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

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

Больше 25 лет я увлекаюсь историей. Немалое время посвятил и изучению философии. Отсюда вполне осознанный взгляд на истоки моих интеллектуальных пристрастий. Если говорить о философских течениях, то мне, скорее, ближе эмпирики, чем идеалисты; мистиков я просто не понимаю. Поэтому Аристотеля я предпочитаю Платону, Юма - Декарту, а перед Паскалем склоняю голову. Всеобъемлющие системы, такие, как у Платона или Канта, пленяют меня, но кажутся фундаментально порочными, поскольку, помоему, они очень далеки от повседневного опыта и особенностей конкретного индивидуума.

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

Всякий раз, когда те или иные идеалы вступают в противоречие, а иногда и в тех ситуациях, где ученые мужи пришли к единодушному согласию, я предпочитаю давать программисту выбор. Мои литературные вкусы еще раз подтверждают нежелание принимать решение только на основе теории и логики. В этом смысле C++ во многом обязан таким романистам и эссеистам, как Мартин А. Хансен, Альбер Камю и Джордж Оруэлл, которые никогда не видывали компьютера, и таким ученым, как Дэвид Грис, Дональд Кнут и Роджер Нидэм. Часто, испытывая искушение запретить какуюто возможность, которая лично мне не нравилась, я останавливался, ибо не считал себя вправе навязывать свою точку зрения другим людям. Я знаю, что многого можно добиться относительно быстро, если последовательно придерживаться логики и безжалостно выносить приговор неправильному, устаревшему и нелогичному образу мыслей. Но при такой модели становятся очень велики человеческие потери. Для меня намного дороже принятие того факта, что люди думают и действуют по разному.

Я предпочитаю медленно - иногда очень медленно - убеждать людей попробовать новые приемы и принять на вооружение те, которые отвечают их нуждам и склонностям. Существуют эффективные методы обращения в другую веру и совершения революции, но я их боюсь и сильно сомневаюсь, что они так уж эффективны в длительной перспективе и по большому счету. Часто, когда кого-то легко удается обратить в религию X, последующее обращение в религию Y оказывается столь же простым, а выигрыш от этого эфемерный. Я предпочитаю скептиков истинно верующим. Мелкий, но неопровержимый факт для меня ценнее большинства теорий, а продемонстрированный экспериментально результат важнее груды логических аргументов.

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

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

Я готов упорно работать над внедрением в сознание идей, которые, по моему глубокому убеждению, принесут пользу людям. Более того, я считаю, что ученые и интеллектуалы должны способствовать распространению своих идей в обществе, чтобы они применялись людьми, а не оставались игрой изощренного ума.

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

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

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

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

    Сообщений 7    Оценка 142        Оценить