Лекция 13
Тема: Объектно-ориентированное программирование.
Основное понятие в ООП – это объект или класс. Концепция объектов предназначена для моделирования (отображения) понятий предметной области в виде программных единиц, объединяющих в себе атрибуты и поведение (состояние и функционирование) соответствующих объектов (сущностей) предметной области.
Класс объектов – это программная структура, в которой данные и функции образуют единое целое и отражают свойства и поведение этого целого в рамках моделируемой предметной области. В объекте присутствуют только те данные, которые необходимы для описания свойств и поведения объектов данного типа. Класс объектов характеризуется уникальным набором свойств и ему присваивается уникальное имя, как и любому типу данных. В качестве переменных программы используются объекты определенного класса. Создаваемые объекты (даже одного класса) могут отличаться значениями свойств и должны отличаться именами.
Инкапсуляция – объединение в единое целое данных и функций, обрабатывающих эти данные. В С++ данные класса и объекта называют элементами данных (полями), а функции – элементами-функциями (методами). Доступ к полям и методам осуществляется через имя объекта и имена полей и методов с использованием операций «.» и «->». Это позволяет изолировать объект. В результате замена или модификация полей или методов объекта не влекут за собой не контролируемых последствий. При необходимости указания имени объекта в теле описания этого объекта используется зарезервированное слово this (указатель на объект в рамках объекта).
Наследование – свойство классов порождать своих потомков и наследовать свойства и (элементы данных и методы) своих родителей. Класс потомок автоматически наследует от родителя се элементы данных и методы, а также может содержать новые элементы данных и методы и даже перекрывать их. Родственные отношения могут отражаться путем инкапсуляции в классе в качестве элементов данных других классов. Например, построить класс стек, у которого элементом класса является стек.
Базовые классы обладают такими абстрактными свойствами, что часто непосредственно в программах не используются, а необходимы только для порождения других классов.
Полиморфизм – свойство объектов-родственников по-разному осуществлять однотипные и даже одинаково поименованные действия. Изменяя алгоритм метода в потомке, наследник получает специфические поведенческие свойства. Для изменения метода необходимо перекрыть его в потомке.
Создание и уничтожение объектов.
Описание класса – это программная структура, которая используется при создании объектов. Конструктор класса создает и инициализирует экземпляры объектов. Деструктор класса выполняет действия, завершающие работу с объектом, например, освобождает динамическую память, восстанавливает экран, закрывает файловые переменные.
Взаимодействие объектов и сообщения.
Благодаря инкапсуляции объекты так хорошо изолируются друг от друга, что необходимо специально заботиться механизме их взаимодействия в программе. Часто связь устанавливают при помощи указателей, что делает программу похожей на структуру данных в динамической памяти. Тогда основным содержанием программы является описание классов и совокупности взаимодействующих объектов (в библиотеках классов для доступа объекта к самому себе используется ключевое слово this). Другим способом обмена информацией между объектами является передача через глобальную переменную (буфер сообщений). Ей один объект присваивает значения, а другой – считывает. Данный способ прост в реализации, но требует тщательного контроля обмена сообщениями между объектами со стороны программиста.
Описание класса.
Описание класса имеет следующий формат:
Class / Struct / Union имя_класса {список_компонентов};
- Одно из ключевых слов Class, Struc или Union указывает на начало описания класса и определяет используемый по умолчанию статус доступа к компонентам класса и влияет на возможности наследования свойств этого класса;
- Имя_класса – идентификатор;
- Список_компонентов – перечень объявлений элементов данных и описаний методов класса.
Каждый компонент класса обладает статусом доступа. В качестве спецификаторов доступа используются ключевые слова:
ü Private (собственный) – делает данные доступными только для методов своего класса. Это позволяет решить проблему защиты данных;
ü Public (общедоступный) – предоставляет общий доступ к тем методам класса, которые организуют связь объекта с внешним миром;
ü Protected (защищенный) – используется в классах при применении механизма наследования. При отсутствии наследования спецификатор Protected идентичен спецификатору Private.
Все компоненты класса, введенные с помощью ключевых слов Struct и Union, являются по умолчанию общедоступными, а с помощью ключевого слова Class – собственными. Для изменения статуса компонентов класса, описанного с помощью ключевых слов Struct и Class, необходимо использовать спецификаторы доступа. Классы, описанные с помощью ключевого слова Union, не могут использоваться в качестве базовых классов при наследовании. У объектов, объявленных на основе подобного класса, статус изменять нельзя.
Пусть требуется описать класс, в котором элементы данных будут собственными, а методы общедоступными. Новый класс будем использовать для сложения двух целых чисел.
сlass Sum
{
private:
int x,y,s;
public:
void setx (int x1) {x=x1;}
void sety (int y1) {y=y1;}
int summa();
}
int Sum :: summa()
{
s=x+y;
return s;
}
В описании класса методы setx(), sety() – представлены полностью, а метод summa – своим прототипом.
Методы setx(), sety() они обеспечивают доступ к компонентным данным; другим функциям компонентные данные недоступны. Описания методов размещены внутри класса (т.е. методы являются встроенными inline). Тело метода реализовано в виде макрорасширения. Этим достигается экономия времени при вызове функции и выходе из нее.
После объявления класса можно описать переменные данного класса:
Sum a;
Для доступа к компонентам объекта можно использовать два способа:
- непосредственное указание имени объекта.
a.Sum :: x или
a.x, a.y, a.s – обращение к элементам данных.
a.setx(3) – вызов метода. Такой способ возможен, если нет методов с таким же именем в базовых классах.
- косвенное задание имени объекта с помощью указателя.
Если объявить указатель
Sum *b=&a; то обращение к элементам данных будет выглядеть
b->x; b->y; b->getx(6);
void main()
{
Sum a, *b=&a;
Int k, l;
Scanf(“%d”,k);
Scanf(”%d”,l);
a.setx(k);
a.sety(l);
printf(“\n Сумма = %d”, b->summa());
}
Конструкторы и деструкторы.
Конструкторы предназначены для инициализации элементов данных объектов. Описание их имеет вид:
Имя_конструктора (список_параметров) {тело_конструктора}
Имя конструктора должно совпадать с именем класса и тип возвращаемого значения не указывается.
Sum (int k=0, int l=0)
{
x=k;
y=l;
}
При вызове конструктора имеются следующие возможности:
ü если конструктор не вызывается явно, то он будет вызван автоматически при создании объекта со значением параметров по умолчанию;
ü если конструктор не описан явно, то он генерируется транслятором автоматически.
Конструктор Sum можно вызвать двумя способами:
Sum A=Sum(1,2);
Sum A(1,2) или Sum A(,2), тогда первому элементу данных будет присвоено нулевое значение.
Деструкторы уничтожают объекты класса и освобождают занимаемую ими память.
Описание их имеет вид:
~ имя_класса( ) {операторы_тела_деструктора}
Например:
~Sum() {}
Деструктор вызывается явно (как вызов функции) при необходимости уничтожения объекта и неявно (автоматически) для локального объекта после окончания блока, в котором объект был объявлен.
Создадим класс clock
#include <mmsystem.h>
class clock
{
protected:
long timestarted;
public:
clock();
float time();
void wait(float tsec);
void reset();
};
clock::clock()
{
timestarted=timeGetTime();
}
void clock::reset()
{
timestarted=timeGetTime();
}
float clock::time()
{
return((timeGetTime()-timestarted)*.001);
}
void clock::wait(float tsec)
{
float x;
if (tsec>60) tsec=60;
x=time()+tsec;
while(time()<x);
}
int main(int argc, char* argv[])
{
clock *c;
float f;
c->reset();
f=c->time();
c->wait(20);
getch();
return 0;
}