Оо программа это совокупность объектов, взаимодействующих между собой




Скачать 124.78 Kb.
НазваниеОо программа это совокупность объектов, взаимодействующих между собой
Дата06.02.2013
Размер124.78 Kb.
ТипПрограмма
Гради Буч «Объектно-ориентированный анализ и проектирование (с примерами на С++)»

Эккель «Философия С++», «Философия Java».

Объектно-ориентированное программирование включает 3 понятия: инкапсуляция, наследование, полиморфизм. Основным элементом данных является объект. В понятие «объект» вкладывают объединение идей абстракции данных и алгоритмов. Основу ООП составляют объектная декомпозиция предметной области, при которой любая система рассматривается как совокупность объектов, взаимодействие которых определяет поведение всей системы в целом. Система программирования может считаться ОО только в том случае, если она поддерживает все вышеизложенные требования. Объекты должны обладать целостностью, включая их описание в виде количественных и качественных характеристик и определения возможных поведений. Эта целостность не может быть нарушена, то есть свойства, которые характеризуют объект и его поведение остаются неизменными. Разработка ОО программы производится в несколько этапов:

  1. объектно-ориентированный анализ. Включает объектную декомпозицию предметной области решаемых задач и разработку объектной модели с точки зрения ООП.

  2. объектно-ориентированное проектирование. По результатам первого этапа позволяет сформировать логическую, статическую и динамическую модели проектируемой системы.

  3. ООП – это методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса (типа), а классы образуют иерархию наследования.

Этап тестирования и отладки функционально не отличаются от структурного программирования.

В ООП значимость проектирования резко возрастает. Неправильно спроектированная объектная модель чаще всего приводит к переработке проекта в целом. Удачно спроектированный программный продукт может быть легко модифицирован и расширен. При этом модификация не требует значительных усилий, за счёт возможности повторного использования кода.

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

ОО программа – это совокупность объектов, взаимодействующих между собой.


Инкапсуляция.

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

ключ_класса имя_класса

{ список_компонентов };

Ключ класса – одно из служебных слов: struct, union, class. Список компонентов – это определение и описание типизированных данных и принадлежащих классу функций. Класс отличается от структурного типа включением компонентных функций. Определение объекта класса производится обычным способом.

имя_класса имя_объекта;

Обращаться к компонентам объекта можно с помощью квалифицированных имён: имя_объекта.имя_класса::имя_компонента

Но чаще используют уточненное имя: имя_объекта.имя_компонента

Если используется указатель на объект, то для обращения к компоненту применим следующий синтаксис: имя_объекта –> имя_компонента

Память при создании объекта выделяется только под компонентные данные. В силу того, что память выделяется только при создании объекта, инициализация компонентных данных в описании типа не допускается. Для инициализации компонентных данных должен использоваться конструктор (спец. функция). Компонентная функция должна быть описана в теле класса, а определена как в теле, так и вне него. Если функция определена в теле класса, то она рассматривается компилятором как inline функция по умолчанию, при условии соблюдения ограничений на inline функцию. Если функция определяется вне класса, то в теле класса записывают только её прототип, а при определении функции заголовок её дополняется именем класса: тип_функции имя_класса::имя_функции (список_параметров)

{ операторы; }

Компонентная функция автоматически получает доступ ко всем компонентам класса.

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


Конструкторы.

Конструктор – специальная функция, предназначенная для инициализации объекта. При определении конструктора в теле класса используется следующий синтаксис:

имя_класса (список_формальных_параметров)

{ операторы; }

Имя конструктора должно совпадать с именем класса, конструктор не может иметь тип возвращаемого результата. Конструктор автоматически вызывается при создании объекта статически или динамически, даже если вызов его не определен. При этом конструктор должен иметь параметры со значениями по умолчанию. Конструктор существует для любого класса, причем, если он явно не определен, он будет автоматически сгенерирован компилятором. Автоматически сгенерированный конструктор не имеет параметров и инициализирует объект со значениями по умолчанию. Числовые данные – нули, строки – пусты, указатели – со значением NULL.

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

имя_класса имя_объекта (фактические параметры)

Здесь создается новый объект с заданным именем.

имя_класса (фактические параметры)

Здесь создается безымянный объект.

Такая форма используется в выражениях, где допускается использование объектов данного класса.


Деструктор.

Если объект создается динамически, то возникает необходимость освобождения памяти при уничтожении объекта. Для выполнения этой операции используется специальный компонент – деструктор. Если деструктор не определен программистом, то он генерируется автоматически. Название деструктора всегда совпадает с именем класса, которому предшествует знак ~. Деструктор не может иметь параметров и не может возвращать результат. Синтаксис определения деструктора:

~ имя_класса ( )

{ операторы десктруктора; }

Вызов деструктора производится автоматически при уничтожении объекта.


Пример описания класса «Точка на экране дисплея».


class point

{ int x, y, color; // private

public:

point (int ix=0, int iy=0, int icolor=WHITE)

{ x=ix;

y=iy;

color=icolor;

}

void show ( );

void hide ( );

void move (int dx, int dy);

int getx ( );

int gety ( );

int getcolor ( );

}

Если имена формальных параметров совпадают с именами компонентных данных, то для определенности перед именем компонентного данного добавляется имя класса и :: (операция определения области видимости).


Ограничения прямого доступа к компонентам класса.

В соответствии с правилами языка С++ если в описании класса используется слово class, то все его компоненты по умолчанию являются собственными, то есть видны только внутри класса. Если используется слово struct, то все компоненты по умолчанию общедоступны, то есть, видны из любого места программы. Если union, то компоненты также общедоступны, но в любой момент виден только один компонент. Изменить статус доступа, принятый по умолчанию можно с помощью спецификаторов доступа: public – общедоступный; private – собственный; protected – защищенный, доступный всем потокам.

Спецификаторы доступа размещаются в тексте описания класса. После спецификатора ставится двоеточие. Действие спецификатора распространяется до следующего спецификатора или до конца описания класса.

Часто компонентные данные в классе определяют как собственные или защищенные с целью недопущения заданий некорректных значений со стороны пользователя.

Дополнения выделены жирным шрифтом.


Статические компоненты.

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

тип имя_класса :: имя_компонента инициализатор

Это предложение должно быть размещено в глобальной области программы. При инициализации под статический компонент выделяется память и ему присваивается значение. Статический компонент общедоступен. Обращаться к статическому компоненту можно до создания объекта данного класса:

имя_класса :: имя_компонента

И после создания объекта:

имя_объекта.имя_компонента

Статической может быть и функция, но вызвать статическую функцию можно только через объект.


Указатель this.

Когда вызывается компонентная функция, ей автоматически неявно передается указатель на тот объект, для которого она вызвана. Этот указатель называется this, и в каждой функции определен следующим образом: имя_класса *const this = адрес_объекта. Этот указатель нельзя определить явно, нельзя изменить его, так как он является константным указателем, в каждую компонентную нестатическую функцию передается как параметр. Этот указатель можно использовать явно в случае совпадения формального параметра и компонентного данного.


Расширяемые объекты. Наследование.

Наследование означает такое отношение между классами, когда один класс заимствует полностью или частично структурную и функциональную части одного или нескольких других классов. В первом случае наследование называется одиночным, и тогда иерархия наследования имеет вид дерева, во втором – множественным, иерархия имеет вид графа. Класс, от которого производится наследование, называют базовым, родительским, предком. Класс, который наследует, называют производным, дочерним, потомком. Одиночное наследование порождает отношение «общее–частное», то есть базовый класс содержит общие для всех своих потомков данные и поведение, а каждый порожденный класс уточняет своего предка, добавляя к нему новые данные и новое поведение. Основное правило при построении иерархии наследования: если в Б есть А, то его можно наследовать от А. Основное преимущество наследования – повторное использование кода.


Определение производного класса.

В определении производного класса приводится список базовых классов, от которых данный класс наследует компоненты. Список от имени класса отделяется двоеточием.

class class1

{ …………

};

сlass class2: class1

{……………..

};

В производном классе можно переопределить как компонентные данные, так и компонентные функции. Если компонент в производном классе переопределен, то соответствующий компонент базового класса по умолчанию становится недоступным. Однако обратиться к компоненту базового класса можно, используя операцию указания области видимости. Если порожденный класс становится базовым для другого класса, то этот класс наследует все видимые компоненты своих предков. Видимыми для потомка являются те компоненты предка, которые имеют статус public или protected. Если потомок определен с помощью слово class, то унаследованные компоненты по умолчанию получают статус private. Если с помощью struct, то компоненты получают статус public. Изменить ситуацию можно с помощью спецификаторов доступа, записываемых перед именем базового класса. Если использовать private, то все унаследованные компоненты получают статус private, protected – protected. Если public, то унаследованные компоненты будут сохранять статус доступа, определенный в базовом классе. Ни базовый, ни производный класс нельзя определить как union.

При определении конструктора производного класса необходимо обеспечить вызов конструктора базового класса со списком фактических параметров.


имя_класса (список формальных параметров):

имя_базового_класса (список фактических параметров)

{ операторы конструктора; }

Конструктор базового класса всегда вызывается до конструктора производного класса. При создании объекта производного класса сначала создается безымянный объект базового класса со всеми его компонентами, а затем создается объект производного класса. Этот процесс состоит в том, что объект базового класса дополняется новыми компонентами. Деструктор производного класса также вызывает деструктор базового класса, но вызов этот производится после выполнения операторов деструктора производного класса. Таким образом, при уничтожении объекта сначала удаляется объект производного класса, а затем объект базового класса.

При вызове компонентных функций сначала поиск вызываемой функции осуществляется внутри класса. Если в этом классе функция не определена, то компилятор обращается к базовому классу, и так вверх по иерархии, пока не будет найдена вызываемая функция. При этом важно помнить, что вызываемая унаследованная функция будет выполняться точно таким же образом, каким была определена в базовом классе.

Пример:

Point

Circle




Show_flake


#include

#include

#include

#include

#include

#include

// класс «точка»

class point

{ protected:

int x, y, color;

public:

point (int ix=0; int iy=0; int icolor=WHITE)

{ x=ix; y=iy; color=icolor; }

void show ( );

void hide ( );

void move (int dx; int dy);

int getx ( );

int gety ( );

int getcolor ( );

};

// класс «окружность»

class circle: pubic point

{ int r;

public:

circle (int ix=0; int iy=0; int icolor=WHITE, int ir): point (ix, iy, icolor)

{ r=ir; }

void show ( );

void hide ( );

void move (int dx, int dy)

int getr ( );

};

// класс «снежинка»

class snow_flake: public point

{ int r, dx, dy;

public:

snow_flake (int ix=0; int iy=0; int icolor=WHITE, int ir): point (ix, iy, icolor)

{ r=ir;

dx=r*cos (M_PI/3); // M_PI=3.14

dy=r*sin (M_PI/3);

}

void show ( );

void hide ( );

void move (int dx, int dy);

int getr ( );

};

// point

void point: : show ( )

{ putpixel (x, y, color);

}

void point: : hide ( )

{ putpixel (x, y, BLACK);

}

void point: : move (int dx, int dy)

{ hide ( );

x+=dx; y+=dy;

show ( );

}

int point: : getx ( )

{ return x; }

int point: : gety ( )

{ return y; }

int point: : getcolor ( )

{ return color; }

// окружность

void circle: : show ( )

{ getcolor (color);

circle (x, y, r);

}

void circle: : hide ( )

{ getcolor (0);

circle (x, y, r);

}

void circle: : move (int dx, int dy)

{ hide ( );

x+=dx; y+=dy;

show ( );

}

int circle: : getr ( )

{ return r; }

// snow_flake

void snow_flake: : show ( )

{ getcolor (color);

line (x–r, x+r, y)

line (x–dx, y–dy, x+dx, y+dy);

line (x–dx, y+dy, x+dx, y–dy);

}

void snow_flake: : hide ( )

{ setcolor (BLACK);

line (x–r, y, x+r, y);

line (x–dx, y–dy, x+dx, y+dy);

line (x–dx, y+dy, x+dx, y–dy);

}

void snow_flake: : move (int dx, int dy)

{ hide ( );

x+=dx; y+=dy;

show ( );

}

void main ( )

{ point p(100, 0, LIGHTRED);

circle c=circle (300, 0, BLUE, 5);

snow_flake s=snow_flake (450, 0, CYAN, 5);

int gd=DETECT, gm;

initgraph (&gd, &gm, “”);

do

{ p.move (0, 6)

c.move (0, 6);

s.move (0, 6);

delay (100);

}

while (!kbhit ( ));

}


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


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

Пример:

Построим на основе ранее созданных классов новый класс – колесо.

// определение классов point, circle, snow_flake

// класс snow_flake1

class snow_flake1: : public snow_flake

{ protected:

int angle;

public:

snow_flake1 (int ix=0, int iy=0, int icolor=WHITE, int ir=20, int iangle=0): show_flake (ix, iy, icolor, ir)

{ angle=iangle;

}

void show ( )

{ if (angle==0)

snow_flake: : show ( );

else if (angle==90)

{ setcolor (color);

Line (x, y–r, x, y+r);

Line (x–dy, y–dx, x+dy, y+dx);

Line (x–dy, y+dx, x+dy, y–dx);

}}

Void hide ( )

{ if (angle==0)

snow_flake: : hide ( );

else if (angle==90)

{ setcolor (BLACK);

Line (x, y–r, x, y+r);

Line (x–dy, y–dx, x+dy, y+dx);

Line (x–dy, y+dx, x+dy, y–dx);

}}}

class wheel: public circle, public snow_flake1

{ public:

wheel (int ix=0, int iy=0, int icolor=WHITE, int ir=20): circle (ix, iy, icolor, ir), snow_flake1 (ix, iy, icolor, ir)

{ }

void show ( )

{ circle: : show ( );

snow_flake1: : show ( );

}

void hide ( )

{ circle: : hide ( );

snow_flake1: : hide ( );

}

void move (int dx, int dy)

{ hide ( );

circle: : x=circle: : x+dx;

circle: : y=circle: : y+dy;

snow_flake: : x=snow_flake: : x+dx;

snow_flake: : y=snow_flake: : y+dy;

if (angle) angle=0;

else angle=90;

show ( );

}

void main ( )

{ wheel w1 (100, 100, LIGHTRED, 20);

int gd=0, gm;

initgraph (&gd, &gm, “”);

do

{ w1.move (3, 0);

delay (100);

} while (!kbhit ( ));

}

В данном примере класс point дважды опосредованно наследуется классом wheel, что приводит к двойному включению объекта этого класса в объект класса wheel. Именно это обстоятельство потребовало отдельно изменять координаты обода и спиц функции move. Кроме того, это приводит к перерасходу оперативной памяти. Чтобы исключить повторное включение объектов класса point в класс wheel следует объявить этот класс виртуальным при определении класса circle и snow_flake:

class circle: virtual public point

{………..}

Class snow_flake: virtual public point

{…………..}

При этом объект класса point будет создаваться один, а в объекты класса circle и snow_flake будет добавлен автоматически указатель на объект класса point. Объект класса wheel при этом будет занимать 20 байт.


Статическое и динамическое связывание.


Статическое связывание означает, что адрес вызываемой функции определяется на этапе компиляции. По умолчанию в языке С++ используется статическое связывание. Динамическое связывание означает, что адрес вызываемой функции определяется во время выполнения программы. Для обеспечения динамического связывания используется спецификатор virtual, который записывается перед заголовком функции, требующей динамического связывания в описании класса.

Для определения адреса вызываемой виртуальной функции во время выполнения программы система выполняет следующие действия:

  1. для каждого класса, имеющего виртуальные функции, объекты которого создаются в программе, компилятором генерируется таблица виртуальных функций vtable, которая содержит адреса виртуальных функций класса.

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

  3. при создании объекта этот компонент заполняется конструктором, для чего компилятор в конструктор добавляет необходимый набор команд.

Вызов виртуальной функции реализуется по цепочке: у объекта получает адрес vtable – в vtable получаем адрес виртуальной функции – переходим по этому адресу для выполнения программного кода. Использование виртуальных функций (show и hide) позволит наследовать move в классах-потомках, при этом перемещение будет производиться адекватно для любого класса-потомка.

class point

{ protected:

int x, y, color;

public:

point (int ix=0, int iy=0, int icolor=WHITE)

{………..}

virtual void show ( );

virtual void hide ( );

void move (int dx, int dy);

}

void point: : move (int dx, int dy)

{ hide ( ); // &(this –> vtable), &(vtable –> hide ( ))

x+=dx; y+=dy;

show ( );

}

За счет генерации компилятором набора команд, обеспечивающих вызов show и hide того класса, объект которого в данный момент активен, функция move может быть унаследована потомками класса point, при этом она будет выполняться корректно для любого объекта иерархии.

void main ( )

{ point p (0, 0, RED);

circle c (639, 0, BLUE, 20);

do

{ p.move (1, 1);

c.move (–1, 1);

}

while (!kbhit ( ));

}


Vtable point

& point: : hide ( )

& point: : show ( )


Vtable circle

& circle: : hide ( )

& circle: : show ( )


P

& vtable point

X

Y

Color


C

& vtable circle

X

Y

Color

R


Таким образом, один и тот же программный код (одна и та же функция) будет по-разному выполняться для объектов разных классов, то есть будет иметь «много форм», что можно было назвать полиморфизмом метода. При перекрытии виртуальных функций в производном классе список параметров и тип результата должен совпадать с виртуальной функцией базового класса, слово virtual в производном классе можно не указывать. Если при этом тип результата не совпадает, компилятор выдает сообщение об ошибке. Если не совпадает список параметров, функция в производном классе считается не виртуальной, однако допускается перегрузка виртуальных функций. Если виртуальная функция вызывается из конструктора, она перестает быть виртуальной.

Похожие:

Оо программа это совокупность объектов, взаимодействующих между собой icon1. системный анализ под системным анализом понимают совокупность приёмов и методов для изучения сложных объектов, представляющих собой совокупность взаимодей-ствующих между собой элементов
Загальна теорія систем. Конспект лекцій Для студентів денної І заочної форм навчання спеціальності 080200 “Інформатика”/Укл.: Кац...
Оо программа это совокупность объектов, взаимодействующих между собой iconПояснительная записка Система образования в РФ представляет собой совокупность взаимодействующих преемственных образовательных программ различных уровней и направленности, федеральных образовательных стандартов и федеральных государственных требований
Система образования в РФ представляет собой совокупность взаимодействующих преемственных образовательных программ различных уровней...
Оо программа это совокупность объектов, взаимодействующих между собой iconИсследование свойств имитационной модели. 9
Математическая модель это совокупность математических объектов и соотношений между ними, адекватно отображающая свойства и поведение...
Оо программа это совокупность объектов, взаимодействующих между собой iconКомпьютерная сеть
Компьютерная сеть – объединение двух или более компьютеров, взаимодействующих между собой с помощью специальных средств связи. Кс...
Оо программа это совокупность объектов, взаимодействующих между собой iconПрограмма ппвс представляет собой совокупность фон-неймановских программ узлов, между которыми организована передача данных с использованием специальных структур
А. А., etc. The complex of control and management scientifically–technological experiments in cosmos. // Modern technologies of automation....
Оо программа это совокупность объектов, взаимодействующих между собой iconРазработка систем управления охраны труда на предприятиях Алтайского края (лекция)
Система управления охраной труда (суот) набор взаимосвязанных или взаимодействующих между собой элементов, устанавливающих политику,...
Оо программа это совокупность объектов, взаимодействующих между собой iconПортфельные инвестиции – Лекция 1 – 08. 09
В общем случае, ип это совокупность нескольких инвестиционных объектов, управляемая ради достижения поставленной цели. Теоретически,...
Оо программа это совокупность объектов, взаимодействующих между собой iconДня два после странного приключения на вечере у Настасьи Филипповны, которым мы закончили первую часть нашего рассказа, князь Мышкин поспешил выехать в
Может быть, даже и наедине между собой сказано было слишком мало. Это были девицы гордые, высокомерные и даже между собой иногда...
Оо программа это совокупность объектов, взаимодействующих между собой iconПарадигмы программирования. Языки программирования
Например, в объектно-ориентированном программировании программист рассматривает программу как набор взаимодействующих объектов, тогда...
Оо программа это совокупность объектов, взаимодействующих между собой iconРеферат ”Локальные компьютерные сети”
Компьютерная сеть – это совокупность компьютеров и различных устройств, обеспечивающих информационный обмен между компьютерами в...
Разместите кнопку на своём сайте:
Библиотека


База данных защищена авторским правом ©lib.znate.ru 2014
обратиться к администрации
Библиотека
Главная страница