On-Line Библиотека www.XServer.ru - учебники, книги, статьи, документация, нормативная литература.
       Главная         В избранное         Контакты        Карта сайта   
    Навигация XServer.ru






 

Язык программирования Си++: этапы эволюции и современное состояние

В.Сухомлин
Научно-исследовательский Вычислительный центр МГУ им. М.В.Ломоносова

1. Основные этапы развития языка

Первые версии языка программирования Си++ (тогда он назывался "Си с классами") были разработаны в начале 80-х годов Бьярном Страуструпом, сотрудником знаменитой AT&T Bell Labs, где ранее были разработаны такие шедевры программирования, как операционная система UNIX и язык программирования Си.
По признанию самого автора языка, Си++ никогда не разрабатывался на бумаге. Проектирование, реализация и документирование новых возможностей происходили фактически одновременно. Единственной целью разработки было создание языка, на котором было бы удобно программировать автору и его друзьям. Если вспомнить историю создания языка Си, то прослеживаются явные аналогии.
За основу был взят популярный в среде профессиональных разработчиков язык программирования Си. Первыми средствами, которыми был расширен Си, стали средства поддержки абстракций данных и объектно-ориентированного программирования.
Как это принято в AT&T, описание нового языка не было опубликовано сразу. Первыми его пользователями стали сами сотрудники Bell Labs. В 1993 впервые была реализована коммерческий транслятор, и сам язык был назван "С++", что можно (имея в виду операцию инкрементирования языка Си) трактовать как увеличенный или расширенный язык Си.
Первым транслятором языка был препроцессор cfront, транслирующий программу на Си++ в эквивалентную программу на Си. И только в конце 80-х годов были реализованы прямые трансляторы, не использующие Си в качестве промежуточного языка. Пионером среди таких трансляторов стал GNU CC.
Если не считать документацию к транслятору cfront, первой книгой с описанием языка стала "The C++ Programming Language" (Addison-Wesley, 1985), переведенная на русский язык и изданная в 1991 году (Страуструп Б. Язык программирования С++. М.: Радио и Связь, 1991).
С этого момента началось его бурное распространение и создание многочисленных реализаций.
Модель реализации ООП была частично позаимствована из языка программирования Simula67 и ориентировалась в основном на возможность эффективной реализации на вычислительных машинах со стандартной архитектурой. Некоторые возможности языка Simula были отклонены, так как, по мнению автора Си++, подталкивали разработчика к плохому стилю программирования. Так, в первых версиях Си++ полностью отсутствовала возможность динамической идентификации типа объекта (run-time type identification, rtti). Основные концепции поддержки ООП в Си++ были изложены Страуструпом в статье "What is Object Oriented Programming".
C 1985 года в язык были введены новые возможности: множественное и виртуальное наследование, шаблоны функций и классов, обработка исключительных ситуаций. Кардинально изменена семантика совместного использования оператора new, изменен синтаксис для вложенных классов.
С момента опубликования и до настоящего момента язык постоянно усовершенствовался и расширялся. Важным этапом в его развитии стала публикация в 1990 году подробного и достаточно строгого описания языка [3]. Сокращенно эту книгу часто называют ARM. Фактически одновременно с этим началась стандартизация языка.
Инициатором стандартизации выступил не автор языка. Более того, Страуструп всегда довольно прохладно относился к попытке его полной стандартизации и выступал за реализации, в которых базовые возможности языка расширялись бы средствами и библиотеками, характерными только для данной реализации.

2. История стандартизации

Объединенный ANSI-ISO (ANSI X3J16; ISO WG21/N0836) комитет начал функционировать в конце 1989 года. Целью его работы является создание единого стандарта для языка Си++ и его библиотечных средств. За основу проекта стандарта было взято описание языка, данное в ARM, и книга [4].
В работе объединенного комитета, функционирующего и по сей день, значительное место занимает изучение (с последующим принятием или отказом от) возможных изменений текста проекта стандарта, а также уточнение различных правил языка. Позволим себе напомнить, что непосредственный предшественник Си++ - язык Си прошел успешно процесс стандартизации. Работа по его стандартизации завершилась в 1989 году, и стандартизованный вариант сейчас известен под именем ANSI Си.
Работа по стандартизации Си++ осложнялась тем, что язык долгое время был открыт для расширений. Сами формулировки правил ARM были недостаточно строги и часто требовали уточнения. Си++ стал довольно громоздким языком (сопоставимым разве что с языком Ada), и ни один человек сейчас не в состоянии точно помнить все его детали и тонкости.
С момента начала стандартизации несколько изменилась и сама идеология Си++. Изначально автор отвергал возможность использования в языке средств динамического определения типов (rtti), однако в текущем проекте стандарта такие средства имеются. Аналогично, в Си++, описанном в ARM, есть довольно жесткие ограничения на возможность определения виртуальных функций, которые сейчас ослаблены. Характерно, что некоторые изменения, требующие пересмотра самой идеологии языка, вносились самим Страуструпом [11]
Изначально планировалось, что окончательная редакция проекта стандарта будет опубликована в 1994 году. Эти сроки были безнадежно провалены. Можно сказать, что последние 3 года процесс стандартизации постоянно находится в состоянии "2 года до завершения". Так, согласно текущему расписанию международный стандарт Си++ должен быть опубликован в конце 1998 года, во что авторы статьи не верят. Даже теперешние, на редкость подробные и громоздкие формулировки семантических правил и ограничений языка явно не дотягивают до математической строгости и оставляют простор для различных трактований.
В ранних версиях проекта стандарта не было раздела, описывающего стандартные библиотеки. Не было описаний библиотеки и в ARM. В то же время реализация библиотеки потокового ввода/вывода, предложенная Andrew Koenig, была повторена в нескольких реализациях и стала стандартом "де-факто". В 1993-1994 годах в проекте стандарта было введено около семи новых разделов для описания библиотеки.
Принципиально важным событием в истории развития стандарта стандартной библиотеки стало включение библиотеки STL (Standard Template Library) разработанной нашим бывшим соотечественником, сотрудником Hewllet-Packard Александром Степановым. В своей статье об истории STL он упоминает, что изначально стремился использовать в Си++ только возможности шаблонов, аналогичные родовым (generic) пакетам и процедурам языка Ada, но после обсуждений со Страуструпом существующих возможностей Си++ изменил свое мнение. Комитет по стандартизации пошел навстречу этим двум гуру, вплоть до того, что в семантику шаблонов были внесены изменения. Этим был создан интересный прецедент в истории языков программирования: не библиотека написана для языка, а сам язык претерпел изменения под влиянием библиотеки, причем разработанной не автором языка.
Согласно расписанию работы комитета по стандартизации, проект стандарта принятый в апреле 1995 года, был предложен для публичного обсуждения и сделан доступен пользователям Internet. Утверждается, что с этого момента никаких серьезных изменений в текст стандарта вноситься не будет. Предполагалось, что в сентябре 1996 года новая редакция проекта стандарта будет вынесена на публичное обсуждение, но не так давно этот этап был перенесен на конец года.

3. Современное состояние языка

Приведем беглое описание новых возможностей языка, введенных с момента публикации ARM и до публикации проекта стандарта в апреле 1995г.

  1. Ведены новые ключевые слова-синонимы для операций (and, and_eq, bitand, bitor, compl, not, or, or_eq, xor, xor-equ).
  2. В языке появился булевский тип данных bool и литералы этого типа true и false.
  3. Появился механизм пространств имен (namespace), облегчающий совместную реализацию проектов группами программистов и позволяющий избегать проблем при использовании нескольких библиотек (ключевые слова namespace и using).
  4. Новое ключевое слово explicit позволяет запретить нежелательное использование конструкторов как функций преобразования типов.
  5. Изменены синтаксис и семантика для изменения прав доступа к членам классов. Новый механизм позволяет использовать единый синтаксис для использования членов пространств имен и членов классов. При этом несколько изменились правила выбора наиболее подходящей из набора совместно используемых функций (на основе использования ключевого слова using).
  6. Добавлен механизм явного использования rtti (включающий операцию с ключевым словом typeid и класс type_info стандартной библиотеки).
  7. Добавлены новые и скорректированы старые способы явного преобразования типов (static_cast, dynamic_cast, const_cast и reinterpret_cast).
  8. Добавлена новая операция new[], парная к операции delete[]; для операций new и delete изменена семантика выражения размещения с целью более безопасной обработки исключительных ситуаций в конструкторах. Стандартная операция new теперь не может вернуть значение 0 в случае нехватки памяти или ошибки, а генерирует исключительную ситуацию. Старый вариант, возвращающий 0, доступен программисту только c явным указанием.
  9. Объявления переменных теперь возможны не только в заголовке for-цикла, но и в операторах if, while, do-while, switch.
  10. Более точно определено время жизни временных объектов в выражении. Теперь время их жизни ограниченно полным выражением, а не концом текущего блока, как сказано в ARM.
  11. Полностью переработано определение шаблонов в Си++. Теперь уже нельзя сказать, что шаблоны Си++ являются лишь слегка замаскированными синтаксическими подстановками. Для них обязателен синтаксический разбор и контроль семантики (в максимально возможной степени). Неоднозначности внутри тел шаблонов, вызываемые неизвестной природой типовых параметров, явно разрешаются посредством ключевого словом typename.
  12. Допускаются шаблонные функции-члены нешаблонных классов, вложенные шаблонные классы и шаблоны - параметры шаблонов.
  13. Виртуальные функции могут возвращать тип, отличный от типа подменяемой функции базового класса, если эти типы являются указателями или ссылками на производный и базовый класс.
  14. Перечислимый тип (enum) окончательно утвердился как самостоятельный тип, не являющийся ни одним из целочисленных типов. Теперь разрешено совместное использование функций, основанное на этом различии; константа 0 перечислимого типа более не считается целочисленным 0, запрещено ее неявное преобразование к указательному типу.
  15. Ослаблено ограничение на тип, возвращаемый операцией ->. Теперь это может быть практически произвольный тип.
  16. Добавлено (на редкость бессмысленное) ключевое слово mutable, позволяющее допускать изменение членов объекта константного класса.
Более подробно некоторые из этих изменений рассмотрены в статье [6].

4. Перспективы

Очень хочется, чтобы стандарт языка был наконец принят. Это может подстегнуть разработчиков систем программирования для Си++ на максимально полную поддержку новых возможностей языка, которые в настоящий момент не реализованы. Хочется, чтобы язык был наконец зафиксирован, и в него не добавлялись новые средства, противоречащие старой идеологии.
И, наконец, несколько замечаний по поводу продолжительных дискуссий на темы вроде "Что лучше - Си или Си++" или "Является ли Си++ языком ООП".
Си++ изначально не был "академическим" языком программирования. Его часто подвергали и подвергают критике за неклассический подход к реализации поддержки ООП, даже за то, что его непосредственным предшественником был язык Си, который явно не подходил на роль "академического" языка, но очень популярен в среде профессиональных разработчиков.
Бесполезно критиковать Си++ за недостаточно неполную или "неправильную" поддержку ООП. Си++ вполне укладывается в формулировку парадигмы ООП, данную Страуструпом. Си++ не является единственным языком ООП и имеет право на свои недостатки и своеобразие.
Сейчас ООП явно поддерживается в нескольких языках программирования, во многих не так как Си++, и разработчик имеет возможность выбора (так, превосходно спроектированный объектно- ориентированный язык Ada95 уже стандартизован). Постоянные упреки в адрес Си++ за "неправильное" понимание ООП кажутся абсолютно несуразными. Даже такие столпы ООП, как Грэди Буч [9] и Роберт Мартин [10] признают, что Си++ является вполне подходящим и неплохим инструментом ООП.
Благодаря своим корням Си++ был быстро воспринят разработчиками, уже имеющими опыт программирования на Си, но не избалованными дорогими и малоэффективными языками "чистого" объектно-ориентированного программирования.
Противопоставлять Си и Си++ тоже не стоит. Один из них ортогонально расширяет другой по нескольким направлениям, которые могут быть использованы независимо.
Си++ допускает использование в нескольких вариантах. Во-первых, он содержит язык программирования Си, точнее, его стандартизованный диалект ANSI C почти целиком. При этом Си++ обладает более мощными и строгими правилами проверки типов. Программист волен использовать лишь часть возможностей Си++, не сталкиваясь при этом с неприятностями, связанными с неполным знанием языка (то есть воспринимать Си++ как "улучшенный" Си). Можно использовать только механизм классов и наследования, не пользуясь возможностями обобщенного (generic) программирования, основанного на шаблонах. Наконец, многим разработчикам приглянулась возможность обработки исключительных ситуаций, не зависящая от других механизмов языка. Взятые вместе, эти возможности предлагают разработчику современный, достаточно гибкий и мощный язык программирования высокого уровня с поддержкой ООП.
Думаем, Си не нуждается в защите. По крайней мере, последние 20 лет показали, что он является исключительно гибким и продуктивным языком, годным как для системного программирования, так и для создания приложений широкого спектра. Почему Си имеет такой успех ? Прежде всего потому, что вместо создания "чистого" языка Керниган и Ричи создали язык, который можно использовать. И в этом они преуспели.
Почему успешен Си++ ? По той же причине.

Литература

  1. The Design and Evolution of C++, B. Stroustrup, Addison-Wesley, 1994. 462 pages.
  2. The C++ Programming Language, Second Edition, Bjarne Stroustrup, 1991, 646 pages.
  3. The Annotated C++ Reference Manual, Margaret A. Ellis and Bjarne Stroustrup, 1990, 453 pages. (Русский перевод М. Эллис, Б. Строуструп. Справочное руководство по языку программирования С++ с комментариями. М.: Мир. 1992)
  4. P.J. Plauger, The Draft Standard C++ Library; Prentice-Hall, 1995.
  5. X3J16/96-0018; WG21/N0836, Working Paper for Draft Proposed International Standard for Information Systems-- Programming Language C++.
  6. Е Зуев, А Кротов "Новые возможности языка Си++", PC Magazine/Russian Edition, #7, 1994.
  7. R. Martin "Why C++", http://www.oma.com
  8. The C Programming Language, Second Edition, B.Kernighan, D. Ritchie, Prentice Hall, 1988. (Русский перевод Керниган, Ричи "Язык программирования Си", М.: Финансы и Статистика, 1992).
  9. Гради Буч. Объектно-ориентированное проектирование с примерами применения: Пер. С англ.- М.: Конкорд, 1992- 519 с.
  10. R. Martin "Designing Object-Oriented C++ Applications using the Booch Method", Prentice Hall, 1995.
  11. Bjarne Stroustrup "New Casts Revisited", ANSI Doc X3J16/93-142.


Литература по C & C++