Основы объектно-ориентированного проектирования

         

C++


Язык C++ создан примерно в 1986 г. Бьерном Страуструпом в AT&T Bell Laboratories (организации, известной помимо других достижений разработкой Unix и C). Он быстро развивался и занял лидирующую позицию в промышленных разработках, стремившихся получить преимущества объектной технологии при сохранении совместимости с языком С. Язык остался почти полностью снизу вверх совместимым (корректная программа на С является в нормальных обстоятельствах корректной программой на C++).

Первые реализации C++ были простыми препроцессорами, преобразующими ОО-конструкции в обычный С, основываясь на технике, описанной в предыдущей лекции. Современные компиляторы, однако, являются "родными" реализациями C++. Теперь трудно найти компилятор С, становящийся одновременно компилятором C++ при включении специального параметра компиляции "C++ конструкции". Это один из показателей успеха. Компиляторы C++ доступны практически для большинства платформ.

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

class POINT { float xx, yy; public: void translate (float, float); void rotate (float); float x (); float y (); friend void p_translate (POINT*, float, float); friend void p_rotate (POINT*, float); friend float p_x (POINT*); friend float p_y (POINT*); };

Первые четыре подпрограммы задают привычный ОО-интерфейс класса. Как показывает этот пример, объявление класса содержит только заголовки подпрограмм, а не их реализации, определяемые отдельно. В связи с этим возникают вопросы области действия объявлений, важные и для компиляторов, и для читателей.

Другие четыре подпрограммы - это примеры "дружественных" подпрограмм. Это понятие характерно для C++ и дает возможность вызова подпрограмм C++ из нормального кода С. Дружественные подпрограммы нуждаются в дополнительном аргументе, задающем объект, к которому применяется операции. Здесь этот аргумент имеет тип POINT*, означающий указатель на POINT.

C++ предлагает широкий набор мощных механизмов:


  • Скрытие информации, включая способность скрывать компоненты от собственных наследников.
  • Поддержка наследования. Первоначальные версии поддерживали только единичное наследование, но теперь язык включает множественное наследование. Дублируемое наследование не обладает покомпонентной гибкостью. (В лекции, посвященной множественному наследованию, отмечалась важность этого свойства.) Вместо этого, разделяется или дублируется весь набор методов дублируемых предков.
  • По умолчанию предлагается статическое связывание, для динамического связывания функция должна быть определена как виртуальная. Подход C++ к этому вопросу подробно обсуждался.
  • Понятие "чистой виртуальной функции" напоминает отложенные методы.
  • Введена более строгая типизация, чем в языке С, но все же разрешающая преобразования типа (кастинг).
  • Сборка мусора обычно отсутствует (из-за приведений типа и использования указателей для массивов и подобных структур), хотя доступны некоторые инструменты для надлежаще ограниченных программ.
  • Из-за отсутствия автоматического управления памятью введено понятие деструктора для явного удаления объектов (понятие, дополняющее понятие конструктора класса - процедуры создания).
  • Обработка исключений не входила в первоначальное определение, но теперь поддерживается большинством компиляторов.
  • Введена некоторая форма попытки присваивания - downcasting.
  • Введена универсальность - "шаблоны". У них два ограничения: отсутствует ограниченная универсальность, и при конкретизации шаблона велика нагрузка на работу во время компиляции (известная в С++ как проблема).
  • Разрешена перегрузка операторов (знаков операций).
  • Введена инструкция assert для отладки, но отсутствуют утверждения для поддержки Проектирования по Контракту (предусловия, постусловия, инварианты классов), соединенные с ОО-конструкциями.
  • Библиотеки, доступны от различных поставщиков, например библиотека MFC (Microsoft Foundation Classes).


Содержание раздела