Шпоры ГОС / ООП
.doc
Ситуация, при которой адрес вызываемого метода неизвестен до момента выполнения программы – называется поздним связыванием (Late binding). Адресация разрешается путем использования таблиц виртуальных методов с адресами методов. Ситуация, при которой адрес вызываемого метода известен в момент компиляции / компоновки -называется ранним связыванием (Early binding). Термины “ раннее связывание” и “ позднее” относятся к этапу, на котором обращение к процедуре связывается с ее адресом. В случае раннего связывания адреса всех функций и процедур известны в тот момент, когда происходят компиляция и компоновка программы. Это позволяет приписать каждому обращению к процедуре соответствующий адрес. В противоположность этому, в случае позднего связывания адрес процедуры не связывается с обращением к ней до этого момента, пока обращение не произойдет фактически, т.е. во время выполнения программы. Полиморфизм, одно из базовых понятий ООП, возможен благодаря позднему связыванию.
|
Объектно-ориентированное программирование — это способ программирования, обеспечивающий модульность программ за счет разделения памяти на области, содержащие данные и процедуры. Области могут использоваться в качестве образцов, с которых по требованию могут делаться копии. Объектно-ориентированный подход основан на систематическом использовании моделей для языково-независимой разработки программной системы, на основе из ее прагматики. Прагматика определяется целью разработки программной системы. В формулировке цели участвуют предметы и понятия реального мира, имеющие отношение к разрабатываемой программной системе. При объектно-ориентированном подходе эти предметы и понятия заменяются их моделями, т.е. определенными формальными конструкциями, представляющими их в программной системе. Таким образом, объектно-ориентированный подход помогает справиться с такими проблемами, как: - уменьшение сложности программного обеспечения; - повышение надежности программного обеспечения; - обеспечение возможности модификации отдельных компонентов программного обеспечения без изменения остальных его компонентов; - обеспечение возможности повторного использования отдельных компонентов программного обеспечения. Применение объектно-ориентированного подхода позволяет разрабатывать хорошо структурированные, надежные в эксплуатации, достаточно просто модифицируемые программные системы. Объектно-ориентированный подход целесообразно использовать на всех этапах жизненного цикла прикладной программной системы, начиная с анализа требований к программной системе и ее предварительного проектирования, и кончая ее реализацией, тестированием и последующим сопровождением. Объектно-ориентированный подход имеет два аспекта: - объектно-ориентированная разработка программного обеспечения; - объектно-ориентированная реализация программного обеспечения.
|
Объектная модель описывает структуру объектов, составляющих систему, их атрибуты, операции, взаимосвязи с другими объектами. В объектной модели должны быть отражены те понятия и объекты реального мира, которые важны для разрабатываемой системы. В объектной модели отражается, прежде всего, прагматика разрабатываемой системы, что выражается в использовании терминологии прикладной области, связанной с использованием разрабатываемой системы. Процесс построения объектной модели включает в себя следующие этапы: - определение объектов и классов; Анализ внешних требований к проектируемой системе позволяет определить объекты и классы объектов, связанные с прикладной проблемой, которую должна решать эта система. - подготовка словаря данных; Необходимо в начале проектирования подготовить словарь данных, содержащий четкие и недвусмысленные определения всех объектов (классов), атрибутов, операций, ролей и др. сущностей, рассматриваемых в проекте. - определение зависимостей между объектами; Из классов исключаются атрибуты, являющиеся явными ссылками на другие классы; такие атрибуты заменяются зависимостями. Зависимости представляют собой абстракцию того же уровня, что и классы, и потому не оказывают непосредственного влияния на будущую реализацию. - определение атрибутов объектов и связей; Корректируются атрибуты классов, вводятся новые атрибуты. Атрибуты выражают свойства объектов рассматриваемого класса, либо определяют их текущее состояние. - организация и упрощение классов при использовании наследования; - дальнейшее исследование и усовершенствование модели. Модель должна быть исследована и отлажена.
|
В иерархии классов соглашение относительно доступности компонентов класса следующее. Собственные (private) методы и данные доступны только внутри того класса, где они определены, а так же дружественным функциям и классам. Защищенные (protected) компоненты доступны внутри класса, в котором они определены, и дополнительно доступны во всех производных классах. Общедоступные (public) компоненты класса видимы из любой точки программы, т.е. являются глобальными. Если считать, что объекты, т.е. конкретные представители классов, обмениваются сообщениями и обрабатывают их, используя методы и данные классов, то при обработке сообщения используются, во-первых, общедоступные члены всех классов программы; во-вторых, защищенные компоненты базовых и рассматриваемого классов и, наконец, собственные компоненты рассматриваемого класса. Собственные компоненты базовых и производных классов, а также защищенные компоненты производных классов недоступны для сообщения и не могут участвовать в его обработке. Описывая класс, нужно оставлять доступ только к тем членам класса, которые необходимы для конкретной работы с объектами; всю сколько-нибудь сложную работу должны брать на себя методы данного класса. Таким образом, ограничение доступа повышает надежность программ, ослабляя взаимозависимость между объектами.
|
|
Класс является основным элементом языка СИ, обеспечивающим ООП. Он представляет собой расширение структур языка СИ, т.е. класс создается на основе уже существующих типов. В классах помимо определения данных допускаются определения выполняемых над ними функций. Кроме того, в них имеются средства управления доступа к данным, позволяющие организовать взаимодействие различных классов друг с другом и классов с обычными функциями. Функции, входящие в класс, часто называются методами. В самом простом виде класс определяется в С++ как структура, работа с элементами которой возможна только через элементы функции. В отличие от структуры класс имеет «приватную» (личную) часть, элементы которой не могут быть доступны иначе как через другие элементы/функции, и «публичную» (общую) часть, элементы которой могут быть использованы непосредственно. Объектом называется определяемая в программе переменная, тип которой определен как класс (структура). «Приватная» часть не обязательно должна следовать в начале определения класса. Для ее обозначения в произвольном месте определения класса можно использовать служебное слово private. Таким образом в первом приближении класс отличается от структуры четко определенным интерфейсом доступа к его элементам. Объекты класса обладают всеми свойствами переменных, в том числе такими, как область действия и класс памяти (время жизни). Последнее свойство наиболее интересно, так как процессы создания и уничтожения объектов класса могут сопровождаться вызовом функций (конструктор и деструктор). Механизм классов позволяет создавать типы в полном соответствии с принципами абстракции данных, т.е. класс задает некоторую структурированную совокупность типизированных данных и позволяет определить набор операций над этими данными. |
Адрес объекта в памяти - называется указателем. Переменная типа «указатель» - это специально объявленная переменная, в которой храниться указатель на переменную определенного типа. Если переменная является указателем, то в объявлении перед ее именем нужно поставить символ *, она сообщит компилятору о том, что это указатель на переменную данного типа: int *i – указатель на объект целого типа. void *k – указатель на объект любого типа (не может быть использован в арифм. и логич. операциях над указателями) Указатели должны инициализироваться либо при своем объявлении, либо в операторе присваивания. Переменная, объявленная как указатель, хранит адрес памяти и информацию о типе объекта, на который ссылается указатель. Операция, обозначаемая знаком &, называется операцией получения адреса: i = &count (переменной i присвоить адрес, по которому расположена переменная count). Операция, обозначаемая знаком *, называется операцией разыменовывания адреса: r = *i (r получает значение, расположенное по адресу i). В качестве модификатора в объявлении указателя может выступать ключевое слово const. Оно указывает, что указатель не может быть изменен в программе. |
Шаблоны дают возможность определять при помощи одного фрагмента кода целый набор взаимосвязанных функций (перегруженных), называемых шаблонными функциями, или набор связанных классов, называемых шаблонными классами. Цель введения шаблонов функций - автоматизация создания функций, которые могут обрабатывать разнотипные данные. В отличие от механизма перегрузки, когда для каждой сигнатуры определяется своя функция, шаблон семейства функций определяется один раз, но это определение параметризуется. Параметризовать в шаблоне функций можно тип возвращаемого функцией значения и типы любых параметров, количество и порядок размещения которых должны быть фиксированы. Для параметризации используется список параметров шаблона. Описание шаблонов функций начинаются с ключевого слова template, за которым следует список формальных параметров шаблона, заключаемый в угловые скобки (< и >); каждому формальному параметру должно предшествовать ключевое слово class или typename, например: Template < class T> или Template < typename T> Можно считать, что параметры шаблона функций являются его формальными параметрами, а типы тех параметров, которые используются в конкретных обращениях к функции, служат фактическими параметрами шаблона. Именно по ним выполняется параметрическая настройка и с учетом этих типов генерируется конкретный текст определения функции. Шаблон семейства классов определяет способ построения отдельных классов подобно тому, как класс определяет правила построения и формат отдельных объектов. В определении класса, входящего в шаблон, особую роль играет имя класса. Оно является не именем отдельного класса, а параметризованным именем семейства классов. Определение шаблона функций и классов может быть только глобальным. Позволяя быстро создавать классы, отличающиеся только типом, шаблоны классов сокращают объем программирования, что, в свою очередь, экономит ваше время.
|
Класс может быть определен внутри блока, например внутри тела функции. Такой класс называется локальным. Локализация класса предполагает недоступность его компонентов вне области определения класса (вне тела функции или блока, в котором он описан или определен). Локальный класс не может иметь статических данных, так как компоненты локального класса не могут быть определены вне текста класса. Внутри локального класса разрешено использовать из объемлющей его области только имена типов, статические (static) переменные, внешние (extern) переменные, внешние функции и элементы перечислений. Из того, что запрещено, важно отметить переменные автоматической памяти. Существует еще одно важное ограничение для локальных классов - их компонентные функции могут быть только встроенными (inline).
|
Дружественные функции (friend-функции) класса определяются вне области действия класса, но имеют доступ к закрытым членам private и protected данного класса. Таким образом, дружественные функции, не являясь членами класса, получают доступ к описанным в нем переменным и методам. Функция не может стать другом класса "без его согласия". Чтобы объявить функцию как друга класса, перед ее прототипом в описании класса ставиться ключевое слово friend. Дружественные функции используются для повышения производительности. Они являются мощным средством. Иногда, есть случаи, когда нет других средств, например, когда функции требуется доступ к внутренней структуре двух и более классов. В таких случаях дружественные функции бывают полезны. Отметим особенности дружественных функций. Дружественная функция при вызове не получает указателя this. Объекты классов должны передаваться дружественной функции только явно через аппарат параметров. При вызове дружественной функции нельзя использовать операции выбора:---имя_объекта.имя_функции---и---указатель_на_объект -> имя_функции Все это связано с тем фактом, что дружественная функция не является компонентом класса. Именно поэтому на дружественную функцию не распространяется и действие спецификаторов доступа (public, protected, private). Место размещения прототипа дружественной функции внутри определения класса безразлично. Итак, дружественная функция: *не может быть компонентной функцией того класса, по отношению к которому определяется как дружественная; *может быть глобальной функцией: Класс может быть дружественным другому классу. Это означает, что все компонентные функции класса являются дружественными для другого класса. Дружественный класс должен быть определен вне тела класса, "предоставляющего дружбу".
|
Создание объекта некоторого класса может быть достаточно сложной процедурой. Поэтому в С++ предусмотрены возможности явного описания процедур создания и уничтожения объектов данного класса. Процедуры создания объектов называются конструкторами, а уничтожения- деструкторами Конструктор - функция-член класса, предназначенная для инициализации переменных класса и резервирования памяти, с помощью оператора new. Имя конструктора совпадает с именем класса, которому он принадлежит. Конструкторы могут принимать аргументы и быть перегруженными, т.е. в классе допускается существование нескольких функций с одинаковым именем. Вызов нужной функции автоматически определяется компилятором по количеству и типам передаваемых параметров. При создании объекта класса нужный конструктор вызывается автоматически. Деструктор - функция-член класса, которая служит для освобождения динамической памяти, занимаемой удаляемым объектом. Деструктор носит имя класса, которое в качестве префикса содержит знак тильды (~). Деструктор вызывается автоматически, когда в программе встречается оператор delete с указателем на объект класса или когда объект прекращает существование. Деструкторы не принимают никаких аргументов и не могут быть перегружены. Применение деструкторов помогает бороться с трудно обнаруживаемыми ошибками, ведущими к утечке памяти и других ресурсов. Деструктор определяется вместе со всеми другими методами объекта в определении типа объекта Если при описании класса конструктор или деструктор не был задан, то компилятор создает их сам.
|
Объектно-ориентированная разработка программного обеспечения связана с применением объектно-ориентированных моделей при разработке программных систем и их компонентов. Объектно-ориентированная разработка может начаться на самом первом этапе жизненного цикла; она не связана с языком программирования, на котором предполагается реализовать разрабатываемую программную систему: этот язык может и не быть объектно-ориентированным. На этапе разработки объекты - это некоторые формальные конструкции (например, прямоугольники с закругленными углами, с помощью которых они изображаются на схемах), никак пока не связанные с их будущей реализацией на одном из языков программирования. Объектно-ориентированные методологии позволяют хорошо понять различные аспекты и свойства разрабатываемой программной системы, что в последующем существенно облегчает ее реализацию, тестирование, сопровождение, разработку новых версий и более существенную модификацию. Существуют следующие объектно-ориентированные методологии разработки программных систем: - OMT (Object Modeling Technique) - SA/SD (Structured Analysis/Structured Design); - JSD (Jackson Structured Development); - OSA (Object-Oriented System Analysis). В технологии OMT проектируемая программная система представляется в виде трех взаимосвязанных моделей: - объектной модели, которая представляет статические, структурные аспекты системы, в основном связанные с данными; - динамической модели, которая описывает работу отдельных частей системы; - функциональной модели, в которой рассматривается взаимодействие отдельных частей системы в процессе ее работы.
|
Отношение агрегации между классами имеет место, когда один класс содержит в качестве составной части объекты другого класса. Иными словами, это отношение «целое/часть», между двумя классами. На диаграмме такая связь обозначается линией со стрелкой в виде незакрашенного ромба, которая указывает на целое. Для реализации нестрогой агрегации часть включается в целое по ссылке: на языке С++ это обычно указатель на соответствующий класс. Таким образом, если этот указатель равен нулю, то компонент отсутствует. В зависимости от решаемой задачи такой компонент может появляться и исчезать динамически в течение жизни объекта целое. Строгая агрегация имеет специальное название – композиция. Она означает, что компонент не может исчезнуть, пока объект целое существует. На следующем рисунке приведен пример агрегации; этот пример интерпретируется следующим образом: документ состоит из нескольких (нуля, или более) абзацев; каждый абзац состоит из нескольких (нуля, или более) предложений.
Наиболее важным свойством отношения агрегации является его транзитивность (если A есть часть B, а B есть часть C, то A есть часть C): так, из рисунка можно заключить, что документ состоит из нескольких (нуля, или более) предложений. Легко видеть, что отношение агрегации антисимметрично (если A есть часть B, то B не есть часть A). Отметим также, что часть свойств целого может быть перенесена и на его части, возможно, с несущественными изменениями (например, контекст каждого оператора некоторой функции совпадает с внутренним контекстом всей функции). |
Инкапсуляция (скрытие информации) является одним из основных базовых понятий объектно-ориентированного программирования. Под инкапсуляцией понимается хранение в одной структуре как данных (констант и переменных), так и функций их обработки (методов). При ООП имеется возможность запретить любой доступ к атрибутам объектов, доступ возможен только через его методы. Внутренняя структура объекта в этом случае скрыта от пользователя, объекты можно считать самостоятельными сущностями, отделенными от внешнего мира. Для того чтобы объект произвел некоторое действие, ему извне необходимо послать сообщение, которое инициирует выполнение нужного метода. Инкапсуляция позволяет изменять реализацию любого класса объектов без опасения, что это вызовет нежелательные побочные эффекты в программной системе. Тем самым упрощается процесс исправления ошибок и модификации программ.
|
Полиморфизм – важная концепция ООП, возможность использования методов с одинаковыми именами для работы с различными типами данных. Полиморфной называется функция, независимо определенная в каждом из группы производных классов и имеющая в них общее имя. Полиморфная функция обладает тем свойством, что при отсутствии полной информации о том, объект какого из производных классов в данный момент обрабатывается, она тем не менее корректно вызывается в том виде, в каком она была определена для данного конкретного класса. В С++ эта возможность реализуется за счет подсистемы позднего связывания, под которым понимается динамическое определение адресов функций во время выполнения программы в противоположность традиционному статическому (раннему) связыванию, осуществляемому во время компиляции. В процессе связывания имена функций заменяются их адресами. Практический смысл полиморфизма заключается в том, что он позволяет посылать общее сообщение о сборе данных любому классу, причем и родительский класс, и классы-потомки ответят на сообщение соответствующим образом, поскольку производные классы содержат дополнительную информацию. Полиморфизм - исключительно мощный метод обобщения однотипных задач для многих разных объектов. В ООП полиморфизм реализуется посредством виртуальных функций и наследования. Полиморфизм позволяет упростить исходные тексты программ, обеспечивает их развитие за счет введения новых методов обработки. |
Виртуальный метод - метод, адрес которого известен только в момент выполнения программы (позднее связывание). С помощью использования виртуальных методов решается проблема доступа к методам, переопределенным в производных классах, через указатель на базовый класс. Виртуальные методы производных классов заменяют методы базового класса везде, где они упоминаются. Чтобы метод был описан как виртуальный, нужно перед его описанием поместить зарезервированное слово VIRTUAL. Виртуальные методы реализуют чрезвычайно мощное средство для обобщения - полиморфизм. Если метод объявлен в родительском типе виртуальным, то все методы с таким же именем в любом порожденном типе должны быть так же объявлены виртуальными. Виртуальной не может быть глобальная функция. Каждый объект, помимо полей данных, описанных для данного класса, содержит ссылку на таблицу адресов виртуальных методов своего класса, инициализируемых на этапе выполнения при помощи конструктора.
|
Каждый объект имеет доступ к собственному адресу с помощью указателя this. Указатель this объекта не является частью самого объекта – то есть указатель this не отражается в результате операции sizeof над этим объектом. Скорее, указатель this передается в объект (компилятором) как неявный первый аргумент в каждом вызове нестатической функции-члена для объекта. Указатель this неявно используется для ссылки как на данные-члены, так и на функции-члены объекта. Тип указателя this зависит от типа объекта и от того объявлена ли функция-член, в которой используется this, как const. В неконстантной функции-члене класса Х указатель this имеет тип X *const (константный указатель на объект Х). В константной функции-члене класса Х указатель this имеет тип const X *const (константный указатель на объект Х, который тоже константный). Имя this является служебным (ключевым) словом. Явно описать или определить указатель this нельзя. В соответствии с неявным определением this является константным указателем, т.е. изменять его нельзя, однако в каждой принадлежащей классу функции он указывает именно на тот объект, для которого функция вызывается. Говорят, что указатель this является дополнительным (скрытым) параметром каждой нестатической компонентной функции. Другими словами, при входе в тело принадлежащей классу функции указатель this инициализируется значением адреса того объекта, для которого вызвана функция. Объект, который адресуется указателем this, становится доступным внутри принадлежащей классу функции именно с помощью указателя this. При работе с компонентами класса внутри принадлежащей классу функции можно было бы везде использовать этот указатель. Одним интересным применением указателя this является предотвращение присваивания объекта самому себе. Самоприсваивание может стать причиной серьезных ошибок в случаях, когда объекты содержат указатели на динамически распределяемую память. Другим применением указателя this является возможность сцепленных вызовов функций-членов класса.
|
Цель перегрузки состоит в том, чтобы функция с одним именем по-разному выполнялась и возвращала всевозможные значения при обращении к ней с различными списками фактических параметров. Для обеспечения перегрузки функций необходимо для каждого имени определить, какие комбинации параметров возможны при обращении к ним. Перегруженные функции должны иметь одинаковые имена, но отличаться по количеству параметров, их типам или расположению. Ниже показан пример объявления перегруженной функции с именем total(), принимающей в качестве аргументов массивы чисел типа int, float и double. int total() (initisize, int iarray[]); float total() (initisize, float farray[]); double total() (initiasize, double darray[]);
|
При использовании технологии ООП решение представляется в виде результата взаимодействия отдельных функциональных элементов некоторой системы, имитирующей процессы, происходящие в предметной области поставленной задачи. В такой системе каждый функциональный элемент, получив некоторое входной воздействие (сообщение) в процессе решения задачи, выполняет заранее определенные действия. Процессом решения управляет последовательность сообщений. Передовая эти сообщения от элемента к элементу, система выполняет необходимые действия. Функциональные элементы системы, параметры и поведение которой определяются условием задачи, обладающие самостоятельным поведением, получили название объектов. Процесс представления предметной области задачи в виде совокупности объектов, обменивающихся сообщениями, называется объектной декомпозицией. - Объектная декомпозиция дает возможность создавать модели меньшего размера путем использования общих механизмов, обеспечивающих необходимую экономию выразительных средств. Использование объектного подхода существенно повышает уровень унификации разработки и пригодность для повторного использования, что ведет к созданию среды разработки и переходу к сборочному созданию моделей. - Объектная декомпозиция позволяет избежать создания сложных моделей, так как она предполагает эволюционный путь развития модели на базе относительно небольших подсистем. - Объектная модель естественна, поскольку ориентированна на человеческое восприятие мира.
|
Классы, для которых нет смысла создавать объекты, объявляют как абстрактные. Абстрактный класс – это класс, содержащий хотя бы один чисто виртуальный метод. Чисто виртуальный метод – это метод, объявленный в классе, но не имеющий конкретной реализации. Синтаксис объявления чисто виртуального метода дополняется конструкцией = 0, например: virtual void Show() = 0; Единственным назначением абстрактного класса является создание соответствующего базового класса, от которого другие классы могут наследовать интерфейс и реализацию. Классы, объекты которых могут быть реализованы, называются конкретными классами (concrete classes). Если в производном классе хотя бы одна чисто виртуальная функция базового класса останется без конкретной реализации, то такой производный класс также будет абстрактным классом, для которого запрещено создавать объекты. Абстрактный класс нельзя употреблять в качестве типа параметра функции, типа возвращаемого функцией значения или как тип при явном приведении. Механизм абстрактных классов разработан для представления общих понятий, которые в дальнейшем предполагается конкретизировать. Эти общие понятия обычно невозможно использовать непосредственно, но на их основе можно, как на базе, построить частные производные классы, пригодные для описания конкретных объектов.
|
