51
посредством объявления виртуальных функций на этапе разработки классов и автоматического создания таблиц виртуальных функций в оперативной памяти на этапе исполнения программного кода. На практике это означает следующее: решение о том, какая конкретная функция должна быть вызвана, откладывается до момента выявления типа объекта на стадии исполнения программы. Вызывается тот вариант кода исполняемой функции(метода), который соответствует типу обрабатываемого в данный момент объекта.
Виртуальные функции(методы) объявляются со спецификацией virtual при первом объявление метода в базовом классе. Виртуальные функции(методы) переопределяются в одном или более произвольном классах. Сигнатуры виртуальных методов должны полностью совпадать, так как при компиляции создаётся таблица виртуальных методов, на основании которой и происходит позднее (динамическое) связывание места вызова функции(метода) с кодом требуемого виртуального функции(метода) из таблицы. С помощью такой таблицы при выполнении программы для каждого типа объекта осуществляется вызов именно своего метода(функции).
Пример: клерк банка принимает оплату. Метод «принимает» может быть интерпретирован по-разному для различных клерков и различных форм оплаты, однако наличие формальных параметров (размер оплаты и назначение платежа) остаются неизменными. Появление новой формы оплаты повлечёт за собой добавление нового класса с перегрузкой виртуального метода приёмки платежей, причём без перестройки и рекомпиляции ранее написанного кода. Таким образом, расширение функционала ранее написанного кода ядра программной системы может быть осуществлено посредством присоединения к ядру новых программных модулей на этапе компоновки обновленного проекта.
В языке С++ виртуальность может быть реализована посредством механизма указателей. Пример применения виртуальности приведён на рисунке 12.
При использовании виртуальных функций имеют место следующие ограничения:
1)прототипы виртуальной функции в базовом классе и во всех производных классах должны соответствовать друг другу (т.е. тип возвращаемого значения, имя функции, число и тип принимаемых параметров должны совпадать), в противном случае функция рассматривается как перегруженная, а не виртуальная;
2)виртуальная функция должна быть компонентом класса;
3)конструктор не может быть виртуальной функцией (в то время как деструктор можно объявить со спецификатором virtual).
52
Примечания:
1)если функция не описана (пропущена) в производном классе, то используется версия базового класса;
2)объявить виртуальными следует функции, определения которых зависят от конкретных параметров объектов;
3)виртуальные функции расширяют наследуемые свойства базовых классов;
4)функция, объявленная виртуальной, сохраняет это свойство для любого производного класса иерархии классов.
Ещё одним вариантом применения виртуализации функций являются абстрактные классы. Абстрактным называется класс, который описывает абстрактные сущности предметной области, не имеющие своего реального отражения в виде конкретных экземпляров. Иными словами, создать объект абстрактного класса невозможно. Например, базовым абстрактным классом может являться «геометрическая фигура». Неопределённую фигуру создать невозможно, однако ничто не мешает инкапсулировать атрибуты толщины линии фигуры, цвет заливки и виртуальные методы прорисовки и перемещения такой фигуры. Как мы знаем, виртуальные операции должны быть определены в производных по отношению к абстрактному базовому классу. Например, в случае прототипа класса «окружность» такой класс будет являться производным от класса «фигура», при этом в классе «окружность» будут доступны (в зависимости от уровня доступа) атрибуты базового абстрактного класса. Виртуальные функции(методы) будут переопределены для частного случая геометрической фигуры (например, для фигуры в виде окружности).
Для описания виртуальных функций базовых абстрактных классов применяется принцип «чистого полиморфизма»:
class Figure
{public: int wideline, backcolor;
virtual void drawFigure()=0; // «чистая» виртуальная функция virtual void removeFigure()=0; // «чистая» виртуальная функция
};
При попытке создать объект на базе класса «Figure» будет получена ошибка. С другой стороны не будет ошибкой создание указателя типа такого класса с целью реализации принципа виртуализации в объектах производных классах.
53
//в базовом классе объявлена и определена виртуальная функция
//tellabout():
class ABCD { public: virtual void tellabout() {cout<<"This is the class ABCD"<<endl;};};
//в производном классе переопределено действие виртуальной функции: class ABCDE: public ABCD
{void tellabout(){cout<<"This is the class ABCDE"<<endl;};};
//в производном классе переопределено действие виртуальной функции: class ABCDEF:public ABCDE
{void tellabout(){cout<<" This is the class ABCDEF "<<endl;};}; //****************************************************** void main(void)
{
ABCD *Ptr ; |
//создание указателя типа базового класса |
||
ABCD |
objABCD; |
//создание объекта базового класса ABCD |
|
ABCDE |
objABCDE; //создание объекта производного класса ABCDE |
||
ABCDEF objABCDEF; //создание объекта класса ABCDEF |
|||
Ptr=&objABCD; |
|
//инициализация указателя |
|
Ptr->tellabout(); |
//обращение к базовому варианту функции |
||
Ptr=&objABCDE; |
|
//переинициализация указателя |
|
Ptr->tellabout(); |
//обращение к новой версии функции |
||
Ptr1=&objABCDEF; |
//переинициализация указателя |
||
Ptr1->tellabout(); |
|
//обращение к третьей версии функции |
|
} |
|
|
|
Рисунок 12 − Пример применения виртуальных функций
Абстрактными классами очень удобно пользоваться на начальных стадиях разработки проекта программной системы, когда поведение сущностей либо не определено совсем, либо определено, но только на уровне прототипов и будет переопределено в дальнейшем при наследовании и расширении иерархии классов объектно-ориентированной модели.
Контрольные вопросы и задания
1.Объясните назначение инкапсуляции класса.
2.С какой целью применяется разделение доступа к элементам класса?
54
3.Какие способы разделения доступа к элементам класса Вы знаете?
4.Какие способы доступа к закрытым элементам класса Вы знаете?
5.Что такое конструкторы класса и каково их назначение?
6.Чем сопровождается создание объекта данного класса?
7.Что определяет перечень параметров при создании объекта?
8.Чем объясняется разнообразность поведения экземпляров одного класса?
9.Чем отличаются функции и методы классов?
10.Какие типы конструкторов класса Вы знаете?
11.Что такое деструкторы класса и каково их назначение?
12.Дайте определение понятию «наследование».
13.Перечислите виды наследования.
14.Каков порядок последовательности работы конструкторов в иерархии классов?
15.Каков порядок последовательности работы деструкторов при наследовании в иерархии классов?
16.Приведите примеры наследования классов.
17.Перечислите способы доступа к наследуемым элементам класса.
18.Дайте определение понятию «позднее связывание».
19.Каким образом может быть обеспечено расширение возможностей программной системы при объектном подходе?
20.Дайте определение понятию «виртуальная функция».
21.В чём заключается назначение виртуальности?
22.Что такое абстрактный класс?
23.Дайте определение видам виртуальности с точки зрения полиморфизма.
2.3. Объектно-ориентированное проектирование
Целью объектно-ориентированного проектирования является реализация возможности преобразования инфологической модели предметной области в объектно-ориентированную модель программной системы. Исходными данными для проектирования являются результаты объектной декомпозиции, а в качестве методов проектирования применяются правила и способы описания статического и динамического состояний системы.
Иными словами, созданная в результате объектно-ориентированного анализа модель предметной области в виде иерархии классов, отражающая статическое состояние системы, дополняется искусственными объектами и классами, которые позволяют описать динамику системы. Такие искусственные элементы
55
предназначены для отражения взаимодействия сущностей предметной области при достижении поставленной цели (например, осуществления продажи товара, приёмки товара на склад, получения наличных в банкомате, регистрации документа и т.д.). Например, своеобразными «двигателями процессов» в программной системе могут служить так называемые менеджеры сообщений, которые, безусловно, являются искусственными по отношению к инфологической модели, но позволяют организовать взаимодействие с пользователями и другими подсистемами вычислительной среды. Описание таких дополнительных элементов системы также выполняется по методу объектной декомпозиции на уровне деклараций в классах, т.е. в виде описания того, что будут делать те или иные функции или методы классов без описания их реализации. Таким образом, объектноориентированный проект можно считать своеобразным описанием постановки задачи на разработку программного кода. В случае применения автоматизированных средств для объектно-ориентированного проектирования результатом этого процесса может являться готовое описание прототипов классов (инкапсуляция) на языке программирования С++ в виде, приемлемом для экспортирования в инструментальную среду, например, MS Visual C++.
Процесс объектно-ориентированного проектирования должен в обязательном порядке тщательным образом документироваться, так как полученный в результате проект не только является отчетным документом и описанием прототипов классов, но и служит очередным этапом очередной итерации, расширяя границы возможности и функциональность продукта, превращая процесс разработки в постоянный процесс усовершенствования продукта, включая его внедрение и послепродажное сопровождение. Для ускорения работы над проектом, обеспечения унификации результатов работ, применения средств автоматизации проектных работ и интегрирования результатов проектирования в инструментальные средства разработки исходного кода, СУБД, и т.д., следует применять современные методики проектирования в виде стандартов и соответствующих нотаций. При потоковой промышленной разработке программных средств применяются автоматизированные средства проектирования, ориентированные на один конкретный стандарт и нотацию.
2.3.1. Язык UML как средство объектно-ориентированного анализа и проектирования
Как и при любом другом способе проектирования в объектноориентированном проектировании существуют свои средства, предназначенные