Программирование презентация

Содержание

Современные программные системы – сложные системы: они отражают сложность реального мира; процесс их разработки сложен (и слабо стандартизирован); программа - дискретная система, а дискретные системы неустойчивы: маленькая

Слайд 1Программирование
Часть 6. Основы ООП
Динамические структуры данных


Слайд 2



Современные программные системы – сложные системы:
они отражают сложность реального мира;
процесс их

разработки сложен (и слабо стандартизирован);
программа - дискретная система, а дискретные системы неустойчивы: маленькая ошибка приводит к значительным последствиям.
Общие свойства сложных систем:
Имеют внутреннюю структуру, то есть состоят из компонент - подсистем, которые, в свою очередь, тоже могут быть разбиты на подсистемы.
Внутренние связи подсистем сильнее связей между этими подсистемами. Это дает возможность по отдельности изучать каждую часть.
Состоят из ограниченного числа типов подсистем, скомбинированных и организованных различным образом.
Являются результатом эволюции более простых систем.


5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera


Слайд 3



Рост сложности и объема ПО на примере ОС Windows (неофициальные данные):








Последствия

ошибок:
Состоят из ограниченного числа типов подсистем, скомбинированных и организованных различным образом.
Являются результатом эволюции более простых систем.


5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera


Слайд 4



Сложности разработки:
Служба Microsoft Consulting Services провела анализ результатов выполнения большого количества

своих программных проектов.
Оказалось, что вероятность провала программных проектов довольно велика.
Только 24% проектов можно признать в той или иной степени успешными,
26% не были завершены,
50% столкнулись с большими проблемами, например, бюджет был превышен вдвое или затрачено в 1,5 раза больше времени.

5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera


Слайд 5


Последствия маленьких ошибок – крах программной системы:
1996 год.
Ошибка взятия целой

части дробного числа при выходе числа с плавающей точкой за диапазон допустимых 16-битовых целых:
double x;

short i = x;
… Вместо:
double x;

if (abs (x) < 32 767) short i = x;
else …;

Результат:

5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera


Слайд 6


5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera
4 июня 1996

года

Взрыв ракеты-носителя Ariane 5
спустя 30 секунд после запуска.

Слайд 7



Способ преодоления сложности – декомпозиция
При проектировании сложной программной системы необходимо разделять

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

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

5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera


Слайд 8


Алгоритмическая декомпозиция
Основана на разделении алгоритмов по модулям системы.
Каждый модуль выполняет

один из этапов общего процесса.
Реализуется средствами структурного программирования

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

5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera


Слайд 9


Объектно-ориентированное программирование (ООП) – методология программирования, основанная на представлении программы в

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

5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera


Слайд 10


Иерархическое упорядочение задач или объектов – важный принцип управления сложностью проекта,

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

5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera

Животное

Туловище

Голова

Глаза

Рот

Уши

Лапы

Хвост




Слайд 11


Объектная иерархия строится по принципу наследования свойств родительских (вышележащих) классов объектов

дочерними (нижележащими) классами.
Родительские классы называют просто родителями (предками), дочерние – потомками








Птица, собака, волк – это типы животных, называемые классами.
Конкретная реализация того или иного класса, например, кот Матроскин, является объектом данного класса.





5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera

Животное

Птица

Млекопитающее

Кошка

Волк

Собака

Орел

Воробей




Слайд 12


Объект характеризуется:
совокупностью своих элементов (и их текущих значений
совокупностью допустимых для объекта

действий
Объединение в едином объекте «материальных» составных частей (обрабатываемых данных), защищенных от внешних воздействий, и действий, манипулирующих этими частями (данными) называют инкапсуляцией.
Наследование – это такое отношение между объектами, когда дочерний объект повторяет элементы структуры и поведения родительского.
 Классы верхних уровней обычно не имеют конкретных экземпляров объектов. (Не существует конкретного живого организма, который назывался бы млекопитающее Бобик). Такие классы называют абстрактными.
Конкретные экземпляры объектов относятся, как правило, к классам самых нижних уровней объектной иерархии (собака Бобик, кот Матроскин).

Полиморфизм – это свойство различных объектов выполнять одно и то же действие (с одним и тем же названием) по-своему.











Родительские типы называют просто родителями (предками), дочерние – потомками





5. Объектно-ориентированное программирование 5.2. Три принципа ООП


Слайд 13


Инкапсуляция – механизм, связывающий воедино программный код и данные, которыми он

манипулирует, а также обеспечивающий их защиту от внешнего вмешательства и неправильного использования.
Класс – определенный пользователем проблемно-ориентированный тип данных, описывающий внутреннюю структуру объектов, которые являются его экземплярами.
Объект (экземпляр класса) находится в таком же отношении к своему классу, в каком переменная находится по отношению к своему типу.
Данные и функции внутри класса называются членами класса.
Данные, входящие в класс, называются данными-членами или полями.
Функции, принадлежащие классу, называют функциями-членами или методами.




5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 14


Синтаксис объявления класса, который не является наследником никакого другого класса:

class Имя_Класса


{
закрытые данные и функции
спецификатор доступа:
данные и функции
спецификатор доступа:
данные и функции

спецификатор доступа:
данные и функции
};




5. Объектно-ориентированное программирование 5.3. Инкапсуляция

Данные

Имя_Класса

Функции


Слайд 15


Пример описания простейшего класса, включающего только данные:

class СBox
{

public:
double m_length;
double m_width;
double m_height;
};

5. Объектно-ориентированное программирование 5.3. Инкапсуляция


m_length

m_width

m_height


Слайд 16


Пример описания простейшего класса, включающего только данные:

class СBox
{

public:
double m_length;
double m_width;
double m_height;
};

5. Объектно-ориентированное программирование 5.3. Инкапсуляция

Спецификатор доступа


Слайд 17


Спецификатор доступа определяет, где в программе будут доступны описанные за ним

члены класса.
Имеются 3 спецификатора доступа:
Public – члены класса будут доступны как в классе, так и в любой точке программы внутри области видимости класса, к которому они относятся.
Private (спецификатор по умолчанию) – члены класса будут доступны только внутри класса (членам класса)
Protected – члены класса будут доступны только внутри класса и внутри потомков класса

Действие спецификатора доступа распространяется до следующего спецификатора или до конца описания класса
По умолчанию, все члены класса, объявленные после ключевого слова class до первого спецификатора доступа имеют спецификацию доступа private

5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 18


Объявление экземпляров класса
CBox mybox1, mybox2;

Объявление указателей на класс
CBox *pbox;
pbox=&mybox1;

Динамическое выделение

памяти для экземпляра класса
CBox *pmybox = new CBox;

Доступ к членам – аналогично структурам
mybox1.m_length = 2.5;
mybox2.m_width = mybox1.m_length;
pmybox->m_height = mybox1.m_length;
pmybox->m_length = pmybox->m_height ;



5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 19


Первый принцип инкапсуляции: объединение данных и методов. Добавим функцию вычисления объема

class

СBox
{
public:
double m_length;
double m_width;
double m_height;
double Volume( );
};

double CBox::Volume()
{
return m_length*m_width*m_height;
}

5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 20


Поработаем с классом CBox

int main() // Working with class CBox
{

CBox mybox1; // Static allocation
mybox1.m_length=2;
mybox1.m_width=3;
mybox1.m_height=4;
cout << mybox1.Volume() << endl; // 24

CBox *pmybox2 = new CBox; // Dynamic allocation
pmybox2->m_length=5;
pmybox2->m_width=6;
pmybox2->m_height=7;
cout << pmybox2->Volume() << endl; // 210
delete pmybox2;
return 0;
}

5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 21


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

явный интерфейс

class CBox
{
double m_length;
double m_width;
double m_height;
public:
void Setlength(double sl) {m_length = sl; }
void Setwidth(double sw) {m_width=sw; }
void Setheight(double sh) {m_height =sh; }
double Getlength() {return m_length;}
double Getwidth() {return m_width;}
double Getheight() {return m_height;}
double Volume( );
};

5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 22


Работаем с измененным классом CBox:


int main() // Working with modified

class CBox
{
CBox mybox1;
mybox1.Setlength(2);
mybox1.Setwidth(3);
mybox1.Setheight(4);
cout << mybox1.Getheight() << " " << mybox1.Volume() << endl; // 4 24

CBox *pmybox2 = new CBox;
pmybox2->Setlength(5);
pmybox2->Setwidth(6);
pmybox2->Setheight(7);
cout << pmybox2->Getlength() << " " << pmybox2->Volume() << endl;
delete pmybox2;
return 0;
}

5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 23


Для чего это нужно: независимость интерфейса от реализации, разрешаются только операции,

определенные через интерфейс

class CBox
{
double m_Size[3]; //now with array !!!
public:
void Setlength(double sl) {m_Size[0] = sl; }
void Setwidth(double sw) {m_Size[1]=sw; }
void Setheight(double sh) {m_Size[2] =sh; }
double Getlength() {return m_Size[0];}
double Getwidth() {return m_Size[1];}
double Getheight() {return m_Size[2];}
double Volume( );
};
double CBox::Volume()
{
return Getlength()*Getwidth()*Getheight();
}


5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 24


В использующей класс программе ничего менять не надо:


int main() // Working

with modified class CBox
{
CBox mybox1;
mybox1.Setlength(2);
mybox1.Setwidth(3);
mybox1.Setheight(4);
cout << mybox1.Getheight() << " " << mybox1.Volume() << endl;

CBox *pmybox2 = new CBox;
pmybox2->Setlength(5);
pmybox2->Setwidth(6);
pmybox2->Setheight(7);
cout << pmybox2->Getlength() << " " << pmybox2->Volume() << endl;
delete pmybox2;
return 0;
}

5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 25


Конструкторы
Конструктор класса – специальная функция класса, которая вызывается при создании

нового объекта класса. Она позволяет инициализировать объекты во время их создания и захватывать ресурсы, необходимые для их функционирования.
Конструкторы всегда называются по имени класса и не имеют типа возврата.
Компилятор предоставляет два типа конструкторов: конструктор по умолчанию и конструктор копирования:
CBox mybox1; // Вызов конструктора по умолчанию

CBox mybox2 = mybox1 // Вызов конструктора копирования

Класс может иметь несколько конструкторов, которые можно перегружать
Если Вы определили какой-либо свой конструктор копирования, Вы обязаны явно определить конструктор по умолчанию.
Стандартный конструктор копирования нельзя использовать при работе с указателями

5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 26


Класс Cbox с перегруженным конструктором и тестовым деструктором

class CBox
{

double m_length;
double m_width;
double m_height;
public:
CBox() {m_length=0; m_width=0; m_height=0;}
CBox(double l,double w) {m_length=l; m_width=w; m_height=0;}
CBox(double l, double w, double h){m_length=l; m_width=w; m_height=h;}
~CBox () {std::cout << "destructor CBox done";}
void Setlength(double sl) {m_length = sl;}
void Setwidth(double sw) {m_width=sw;}
void Setheight(double sh) {m_height =sh;}
double Getlength() {return m_length;}
double Getwidth() {return m_width;}
double Getheight() {return m_height;}
void Print (){std::cout <<"\nL="<

Слайд 27


В конструкторе инициализацию переменных-членов класса можно делать в теле конструктора:

CBox() {m_length=0;

m_width=0; m_height=0;}

CBox(double l,double w) {m_length=l; m_width=w; m_height=0;}

CBox(double l, double w, double h){m_length=l; m_width=w; m_height=h;}

Или вне тела:

CBox() : m_length(0), m_width(0), m_height(0) { }

CBox(double l,double w): m_length(l), m_width(w), m_height(0) { }

CBox(double l, double w, double h): m_length(l), m_width(w), m_height(h) { }



5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 28


Поработаем с этим классом


int main() // Working with class CBox
{

CBox

mybox1; mybox1.Print(); // L=0 W=0 H=0
CBox mybox2(1,2,3); mybox2.Print(); // L=1 W=2 H=3
CBox mybox3(1,2); mybox3.Print(); // L=1 W=2 H=0
CBox mybox4=mybox2; mybox4.Print(); // L=1 W=2 H=3

mybox1=mybox2; mybox1.Print(); // L=1 W=2 H=3
_getch();
return 0; // Destructor done
}

5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 29


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

указателями


class CPoint
{
short m_a;
short *m_k;
public:
CPoint() {m_a=4; m_k=new short (1);} // Consructor

~CPoint() {delete m_k; m_k=NULL;} // Destructor

void Setk(short k) {*m_k=k;}
void Seta(short a) {m_a=a;}
void Print ()
{std::cout << "\n a="<

Слайд 30


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

указателями


int main() // Working with class CPoint
{
CPoint x; x.Print(); // a= 4 k=003B6188 *k=1
CPoint y=x; y.Print(); // a= 4 k=003B6188 *k=1

x.Setk(5);
x.Seta(8);

x.Print(); // a= 8 k=003B6188 *k=5
y.Print(); // a= 4 k=003B6188 *k=5

return 0; // program crash while try to free the same
} // memory second time!

5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 31


Надо определить свой конструктор копирования


class CPoint
{
short m_a;

short *m_k;
public:
CPoint() {m_a=4; m_k=new short (1);}
CPoint (const CPoint &p) {m_a=p.m_a; m_k=new short(*p.m_k);}
~CPoint() {delete m_k; m_k=NULL;}

void SetK(short k) {*m_k=k;}
void SetA(short a) {m_a=a;}
void Print () {std::cout << "\n a="<

Слайд 32


Та же программа, теперь дает ожидаемый результат


int main() // Working with

class CPoint
{
CPoint x; x.Print(); // a= 4 k=003B6188 *k=1
CPoint y=x; y.Print(); // a= 4 k=003B6260 *k=1

x.SetK(5);
x.SetA(8);

x.Print(); // a= 8 k=003B6188 *k=5
y.Print(); // a= 4 k=003B6260 *k=1

return 0;
}

5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 33


Деструкторы
Деструктор класса – специальная функция класса, которая уничтожает объект, когда

необходимость в нем отпадает или время его жизни завершено.
Имя деструктора совпадает с именем класса, которому предшествует знак ~(тильда).
Деструктор не принимает параметров и не возвращает значения. Таким образом, деструктор в классе всегда один.
Компилятор предоставляет деструктор по умолчанию.
Однако, если Вы захватывали какие-либо ресурсы при создании объекта (например, динамически выделяли память), Вы обязаны переопределить деструктор для корректного освобождения ресурсов
Это было сделано в предыдущем примере:
~CPoint() {delete m_k; m_k=NULL;}

5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 34


Объекты в памяти

CBox box1, box2, box3
5. Объектно-ориентированное программирование 5.3. Инкапсуляция
box1
box2
box3
m_length
m_width
m_height
Setheight()
Setwidth()
Setlength()
Getheight()
Getwidth()
Getlength()
Volume()
m_length
m_width
m_height
m_length
m_width
m_height




Слайд 35


Указатель this

double CBox::Volume()
{
return m_length * m_width * m_height;
}
box1.Volume(); box2.Volume();

box3.volume()



double CBox::Volume(const CBox* this)
{
return this->m_length * this->m_width * this->m_height;
}
CBox::Volume(&box1);





5. Объектно-ориентированное программирование 5.3. Инкапсуляция


Слайд 36


Статические переменные или константы - члены класса

class CBox
{

double m_length;
double m_width;
double m_height;
static int m_noboxes;

public:
CBox() {m_length=0; m_width=0; m_height=0; m_noboxes++}
void Setlength(double sl) {m_length = sl; }
void Setwidth(double sw) {m_width=sw; }
void Setheight(double sh) {m_height =sh; }
double Getlength() {return m_length;}
double Getwidth() {return m_width;}
double Getheight() {return m_height;}
double Volume( );
};





5. Объектно-ориентированное программирование 5.3. Инкапсуляция

Статические данные-члены класса только объявляются внутри класса. Они должны быть определены вне класса следующим образом:
int CBox::m_noboxes; // или
int CBox::m_noboxes=0;


Слайд 37


Объекты в памяти

CBox box1, box2, box3;
5. Объектно-ориентированное программирование 5.3. Инкапсуляция
box1
box2
box3
m_length
m_width
m_height
Setheight()
Setwidth()
Setlength()
Getheight()
Getwidth()
Getlength()
Volume()
m_length
m_width
m_height
m_length
m_width
m_height



m_noboxes



Слайд 38


Статические функции - члены класса

class CBox
{
double

m_length;
double m_width;
double m_height;
static int m_noboxes;
public:
CBox() {m_length=0; m_width=0; m_height=0; m_noboxes++}
void Setlength(double sl) {m_length = sl; }
void Setwidth(double sw) {m_width=sw; }
void Setheight(double sh) {m_height =sh; }
double Getlength() {return m_length;}
double Getwidth() {return m_width;}
double Getheight() {return m_height;}
double Volume( );
static Getnoboxes() {return m_noboxes;}
};





5. Объектно-ориентированное программирование 5.3. Инкапсуляция

Статические функции-члены класса имеют доступ только к статическим членам класса. Для доступа к нестатическим членам они должны получить адрес объекта как параметр


Слайд 39


Константные объекты
const CBox bx1(10, 15, 6);

Константные функции-члены класса

class CBox
{

double m_length;
double m_width;
double m_height;
static int m_noboxes;
public:
const double Getlength() {return m_length;}
const double Getwidth() {return m_width;}
const double Getheight() {return m_height;}
const double Volume( );
};





5. Объектно-ориентированное программирование 5.3. Инкапсуляция

Значения полей константного объекта после инициализации не могут изменяться

Константная функция не может изменять значения переменных-членов класса


Слайд 40
Организация связанных структур данных.


struct Node
{
Node *link;
// Информационная часть inf
// …
};








5. Объектно-ориентированное

программирование 5.4. Связанные динамические структуры данных

Слайд 41


Основные виды связанных динамических структур данных:

Линейные списки – данные динамической структуры,

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











5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных


Слайд 42


Основные виды связанных динамических структур данных:

Кольцевые списки – имеют дополнительную связь

между первым и последним элементами.












Очередь – частный случай линейного списка – разрешено только 2 действия – добавление элементов в конец (хвост) и удаление из начала (головы) списка.
Стек – частный случай линейного списка – разрешено только 2 действия – добавление и удаление элементов с одного конца (головы) стека.

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных


Слайд 43
Основные виды связанных динамических структур данных:

Деревья – иерархические динамические структуры произвольной

конфигурации.








5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных


Слайд 44
Стек как объект-контейнер

class CStack
{
struct m_Node
{
m_Node *m_next;
int m_item;
};
m_Node *m_head;
int m_size;
public:
CStack() {m_head=NULL; m_size=0;}

//Constructor
~CStack(); // Destructor
void Push(int item);
int Pull();
void Print();
};















5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных


Слайд 45
Работа со стеком
1. Исходное состояние
CStack() {m_head=NULL; m_size=0;}











2. Добавление элемента
void

CStack::Push(int item)
{
m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_head

cur

m_size=0


Слайд 46
Работа со стеком
1. Исходное состояние
CStack() {m_head=NULL; m_size=0;}











2. Добавление элемента
void

CStack::Push(int item)
{
m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_head

cur

m_size=0


Слайд 47
Работа со стеком
1. Исходное состояние
CStack() {m_head=NULL; m_size=0;}











2. Добавление элемента
void

CStack::Push(int item)
{
m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_head

cur

m_size=0


Слайд 48
Работа со стеком
1. Исходное состояние
CStack() {m_head=NULL; m_size=0;}











2. Добавление элемента
void

CStack::Push(int item)
{
m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_head

cur

m_size=0


Слайд 49
Работа со стеком
1. Исходное состояние
CStack() {m_head=NULL; m_size=0;}











2. Добавление элемента
void

CStack::Push(int item)
{
m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_head

cur

m_size=1


Слайд 50
Работа со стеком
1. Исходное состояние
CStack() {m_head=NULL; m_size=0;}











2. Добавление элемента
void

CStack::Push(int item)
{
m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_head

m_size=1


Слайд 51
Работа со стеком
1. Исходное состояние
CStack() {m_head=NULL; m_size=0;}











2. Добавление элемента
void

CStack::Push(int item)
{
m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_head

m_size=1


Слайд 52
Работа со стеком











2. Добавление еще одного элемента
void CStack::Push(int item)
{

m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=1


Слайд 53
Работа со стеком











2. Добавление еще одного элемента
void CStack::Push(int item)
{

m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=1

cur


Слайд 54
Работа со стеком











2. Добавление еще одного элемента
void CStack::Push(int item)
{

m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=1

cur


Слайд 55
Работа со стеком











2. Добавление еще одного элемента
void CStack::Push(int item)
{

m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=1

cur


Слайд 56
Работа со стеком











2. Добавление еще одного элемента
void CStack::Push(int item)
{

m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=1

cur


Слайд 57
Работа со стеком











2. Добавление еще одного элемента
void CStack::Push(int item)
{

m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2

cur


Слайд 58
Работа со стеком











3. Добавление еще одного элемента
void CStack::Push(int item)
{

m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2


Слайд 59
Работа со стеком











4. Удаление элемента
int CStack::Pull()
{
int item=m_head->m_item;
m_Node*

tmp=m_head;
m_head=m_head->m_next;
delete tmp;
m_size--;
return item;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2


Слайд 60
Работа со стеком











4. Удаление элемента
int CStack::Pull()
{
int item=m_head->m_item;
m_Node*

tmp=m_head;
m_head=m_head->m_next;
delete tmp;
m_size--;
return item;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2

item


Слайд 61
Работа со стеком











4. Удаление элемента
int CStack::Pull()
{
int item=m_head->m_item;
m_Node*

tmp=m_head;
m_head=m_head->m_next;
delete tmp;
m_size--;
return item;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2

item

tmp


Слайд 62
Работа со стеком











4. Удаление элемента
int CStack::Pull()
{
int item=m_head->m_item;
m_Node*

tmp=m_head;
m_head=m_head->m_next;
delete tmp;
m_size--;
return item;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2

item

tmp


Слайд 63
Работа со стеком











4. Удаление элемента
int CStack::Pull()
{
int item=m_head->m_item;
m_Node*

tmp=m_head;
m_head=m_head->m_next;
delete tmp;
m_size--;
return item;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2

item

tmp


Слайд 64
Работа со стеком











4. Удаление элемента
int CStack::Pull()
{
int item=m_head->m_item;
m_Node*

tmp=m_head;
m_head=m_head->m_next;
delete tmp;
m_size--;
return item;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=1

item

tmp


Слайд 65
Работа со стеком











4. Удаление элемента
int CStack::Pull()
{
int item=m_head->m_item;
m_Node*

tmp=m_head;
m_head=m_head->m_next;
delete tmp;
m_size--;
return item;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=1

item


Слайд 66
Работа со стеком











5. Печать элементов
void CStack::Print()
{
std::cout

size = " << m_size <<"\n";
for (m_Node *cur=m_head; cur!=NULL; cur=cur->m_next)
std::cout << cur->m_item << std::endl;
std::cout << "End of printed list\n\n";
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2


Слайд 67
Работа со стеком











5. Печать элементов
void CStack::Print()
{
std::cout

size = " << m_size <<"\n";
for (m_Node *cur=m_head; cur!=NULL; cur=cur->m_next)
std::cout << cur->m_item << std::endl;
std::cout << "End of printed list\n\n";
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2

cur

cout


Слайд 68
Работа со стеком











5. Печать элементов
void CStack::Print()
{
std::cout

size = " << m_size <<"\n";
for (m_Node *cur=m_head; cur!=NULL; cur=cur->m_next)
std::cout << cur->m_item << std::endl;
std::cout << "End of printed list\n\n";
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2

cur

cout


Слайд 69
Работа со стеком











5. Печать элементов
void CStack::Print()
{
std::cout

size = " << m_size <<"\n";
for (m_Node *cur=m_head; cur!=NULL; cur=cur->m_next)
std::cout << cur->m_item << std::endl;
std::cout << "End of printed list\n\n";
return;
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2

cur


Слайд 70
Работа со стеком











6. Очистка памяти
CStack::~CStack(void)
{
m_Node *cur=NULL;
while (m_head!=NULL)

{
cur=m_head;
m_head = m_head->m_next;
delete cur;
}
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head


Слайд 71
Работа со стеком











6. Очистка памяти
CStack::~CStack(void)
{
m_Node *cur=NULL;
while (m_head!=NULL)

{
cur=m_head;
m_head = m_head->m_next;
delete cur;
}
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

cur


Слайд 72
Работа со стеком











6. Очистка памяти
CStack::~CStack(void)
{
m_Node *cur=m_head;
while (m_head!=NULL)

{
cur=m_head;
m_head = m_head->m_next;
delete cur;
}
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

cur


Слайд 73
Работа со стеком











6. Очистка памяти
CStack::~CStack(void)
{
m_Node *cur=m_head;
while (m_head!=NULL)

{
cur=m_head;
m_head = m_head->m_next;
delete cur;
}
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

cur


Слайд 74
Работа со стеком











6. Очистка памяти
CStack::~CStack(void)
{
m_Node *cur=m_head;
while (m_head!=NULL)

{
cur=m_head;
m_head = m_head->m_next;
delete cur;
}
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

cur


Слайд 75
Работа со стеком











6. Очистка памяти
CStack::~CStack(void)
{
m_Node *cur=m_head;
while (m_head!=NULL)

{
cur=m_head;
m_head = m_head->m_next;
delete cur;
}
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2

cur


Слайд 76
Работа со стеком











6. Очистка памяти
CStack::~CStack(void)
{
m_Node *cur=m_head;
while (m_head!=NULL)

{
cur=m_head;
m_head = m_head->m_next;
delete cur;
}
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2

cur


Слайд 77
Работа со стеком











6. Очистка памяти
CStack::~CStack(void)
{
m_Node *cur=m_head;
while (m_head!=NULL)

{
cur=m_head;
m_head = m_head->m_next;
delete cur;
}
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2

cur


Слайд 78
Работа со стеком











6. Очистка памяти
CStack::~CStack(void)
{
m_Node *cur=m_head;
while (m_head!=NULL)

{
cur=m_head;
m_head = m_head->m_next;
delete cur;
}
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2

cur


Слайд 79
Работа со стеком











6. Очистка памяти
CStack::~CStack(void)
{
m_Node *cur=m_head;
while (m_head!=NULL)

{
cur=m_head;
m_head = m_head->m_next;
delete cur;
}
}

5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

m_head

m_size=2


Слайд 80
Подведем итоги: класс CStack: описание

#pragma once
class CStack // Описание

расположено в файле Stack.h
{
struct m_Node
{
m_Node *m_next;
int m_item;
};
m_Node *m_head;
int m_size;
public:
CStack() {m_head=NULL; m_size=0;} //Constructor
~CStack(); // Destructor
void Push(int item);
int Pull();
void Print();
};











5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных

-m_head
-m_size

CStack

+CStack
+~CStack
+Push
+Pull
+Print

-m_next
-m_item

m_Node



Слайд 81
Подведем итоги: класс CStack: реализация



#include "StdAfx.h"
#include "Stack.h"

CStack::~CStack(void) // Реализация: файл

CStack.cpp
{
m_Node *cur=m_head;
while (m_head!=NULL)
{
cur=m_head;
m_head = m_head->m_next;
delete cur;
}
}











5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных


Слайд 82
Подведем итоги: класс CStack: реализация


void CStack::Push(int item) // Продолжение файла CStack.cpp
{

m_Node *cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}
int CStack::Pull()
{
int item=m_head->m_item;
m_Node* tmp=m_head;
m_head=m_head->m_next;
delete tmp;
m_size--;
return item;
}











5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных


Слайд 83
Подведем итоги: класс CStack: реализация



void CStack::Print() // Окончание файла CStack.cpp
{

std::cout << "\nPrinting stack, size = " << m_size <<"\n";
for (m_Node *cur=m_head; cur!=NULL; cur=cur->m_next)
std::cout << cur->m_item << std::endl;
std::cout << "End of printed list\n\n";
return;
}











5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных


Слайд 84
Подведем итоги: класс CStack: тестирующая функция main


#include "stdafx.h"
using namespace std;

int main()

// файл MyStack.cpp
{
char k='0';
int item;
CStack MyStack;

cout << "\na - add an element to the stack";
cout << "\nd - delete the last element";
cout << "\np - print the stack";
cout << "\nesc - exit\n";











5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных


Слайд 85
Подведем итоги: класс CStack: тестирующая функция main


while (cout

<< "\nEnter:", k=_getche(), k!=27)
{
switch (k)
{
case 'a':
{
cout<<"\nEnter an item: "; cin >> item;
MyStack.Push(item);
cout <<"The item has been added\n";
break;
}
case 'd': cout << "\nDeleted. The item is "< case 'p': MyStack.Print(); break;
}
}
return 0; //Destructor will be called here
}











5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных


Слайд 86


Шаблон классов – класс, в котором определены данные и методы, но

фактический тип (типы) данных задаются в качестве параметра (параметров) при создании объекта класса.
Шаблоны классов позволяют многократно использовать один и тот же код, позволяющий компилятору автоматизировать процесс реализации типа.
Основные свойства шаблона классов:
Шаблон позволяет передать в класс один или несколько типов в виде параметров
Параметрами шаблона могут быть не только типы, но и константные выражения
Объявление шаблона должно быть только глобальным
Статические члены-данные специфичны для каждой реализации шаблона
Спецификация и реализация шаблона классов при раздельной компиляции обязательно должны находиться в одном файле

5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 87


Объявление шаблона классов

Объявление шаблона классов начинается со строки, имеющей следующий

формат:

template

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

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

template
Тип_функции Имя_шаблона < Параметр_Типа1, … , Параметр_ТипаN>
::Имя_функции (список параметров функции)

5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 88


Объявление шаблона классов

Параметры шаблона могут иметь значения по умолчанию. В

этом случае в объявлении шаблона классов в угловых скобках после имени параметра типа ставится знак = , а за ним указывается значение по умолчанию.
Например,

template

5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 89


Объявление объектов шаблона классов

При объявлении переменных шаблона классов (объектов шаблона)

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

Имя_Шаблона <Тип1, … , ТипN> Имя_Объекта;

5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 90


Пример шаблона классов: массив как объект
Объявление класса:

template

Size=100>
class MyArray
{
U m_array [Size];
public:
MyArray(void) {for (int i=0; i<=Size-1; i++) m_array[i]=0;}
~MyArray(void) {}
U Get (int i);
void Put (int i, U x);
void Print(void)
{for (int i=0; i<=Size; i++) std:: cout << m_array[i] << " " ;}
};


5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 91


Пример шаблона классов: массив как объект
Определения методов

template

Size>
U MyArray < U, Size>::Get (int i)
{
if (i<0) i=0; if (i>Size-1) i=Size-1;
return m_array[i];
}

template
void MyArray < U, Size>::Put (int i, U x)
{
if (i<0) i=0; if (i>Size-1) i=Size-1;
m_array[i]=x;
return;
}




5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 92


Пример шаблона классов: массив как объект
Функция main

int main()
{
MyArray

darray;
MyArray <> iarray;

darray.Put(1,3.14);
iarray.Put(0,2);
darray.Put(0,iarray.Get(0));
darray.Print();

_getch();
return 0;
}



5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 93


Шаблон класса стек . Файл TStack.cpp

#pragma once
#include "StdAfx.h“


template
class

TStack
{
struct m_Node
{
m_Node *m_next;
T m_item;
};
m_Node *m_head;
int m_size;

5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 94


Шаблон класса стек. Файл TStack.cpp (продолжение)

public:
TStack(): m_head(NULL),

m_size(0){ } //Constructor
~TStack(); // Destructor
void Push(T item);
T Pull();
void Print(); //works only with simple types
void Interpush();
void Interpull();

};


5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 95


Шаблон класса стек. Файл TStack.cpp (продолжение)

template
TStack::~TStack(void) // Destructor


{
m_Node *cur=m_head;
while (m_head!=NULL)
{
cur=m_head;
m_head = m_head->m_next;
delete cur;
}
}

5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 96


Шаблон класса стек. Файл TStack.cpp (продолжение)

template
void TStack::Push(T item)
{
m_Node

*cur=new m_Node;
cur->m_item = item;
cur->m_next = m_head;
m_head = cur;
m_size++;
return;
}


5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 97


Шаблон класса стек. Файл TStack.cpp (продолжение)

template
T TStack::Pull()
{
T item=m_head->m_item;
m_Node*

tmp=m_head;
m_head=m_head->m_next;
delete tmp;
m_size--;
return item;
}


5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 98


Шаблон класса стек. Файл TStack.cpp (продолжение)

template
void TStack::Print()
{
std::cout

"\nPrinting stack, size = " << m_size <<"\n";
for (m_Node *cur=m_head; cur!=NULL; cur=cur->m_next)
std::cout << cur->m_item << std::endl;
std::cout << "End of printed list\n\n";
return;
}


5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 99


Шаблон класса стек. Файл TStack.cpp (продолжение)

template
void TStack::Interpush()
{
T item;
cout

an item: "; cin >> item;
Push(item);
cout <<"The item has been added\n";
return;
}

template
void TStack::Interpull()
{
cout << "\nDeleted. The item is "< return;
}

5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 100


Шаблон класса стек. Файл MyTStack.cpp (продолжение)

#include "stdafx.h"
#include "TStack.cpp"
using namespace std;

int

main()
{
TStack MyStack;
const char *menu[ ][2]=
{{"a"," - add an element to the stack"},
{"d"," - delete the last element"},
{"p"," - print the stack"},
{"e"," - exit\n"}};
int size_menu = (sizeof menu)/(sizeof menu[0][0])/2;
for (int i=0; i<=size_menu-1; i++)cout << endl << menu[i][0]<

5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 101


Шаблон класса стек. Файл MyStack.cpp (продолжение)

while (true)

{
cout << "\nEnter:"; char k= _getche();
if (k==*menu[0][0]) MyStack.Interpush();
if (k==*menu[1][0]) MyStack.Interpull();
if (k==*menu[2][0]) MyStack.Print();
if (k==*menu[size_menu-1][0]||k==27) break;
}
return 0; //Destructor will be called here
}


5. Объектно-ориентированное программирование 5.5. Шаблоны классов


Слайд 102


5. Объектно-ориентированное программирование 5.6. Перегрузка операций
В языке С++ операторы рассматриваются

как функции, имеющие следующий прототип:
Имя_Типа operator @ (список_параметров);
Здесь символом @ обозначено имя оператора

Операторы, как и функции, можно перегружать.
Перегружать можно все существующие в С++ операторы, кроме: . (точка, оператор доступа к члену класса), .*(оператор доступа к члену класса через указатель), :: (оператор разрешения области видимости, :? (условный оператор), #,## (препроцессорные операторы), sizeof и typeof, операторы преобразования типов данных static_cast, const_cast, reinterpret_cast, dynamic_cast.
Перегруженные операторы можно определять и как члены класса, для которого выполняется перегрузка и как функции не члены класса (часто – дружественные функции).
Один оператор может быть перегружен несколько раз для различных типов аргументов.


Слайд 103


5. Объектно-ориентированное программирование 5.6. Перегрузка операций
Перегрузка операторов должна удовлетворять следующим

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




Слайд 104


5. Объектно-ориентированное программирование 5.6. Перегрузка операций
Рассмотрим перегрузку операций сразу на

примере шаблона класса CVecn, позволяющего работать с n-мерными векторами, заданными своими координатами в прямоугольной системе координат.
Внутренне представление этого вектора – одномерный массив элементов типа double размером n элементов.
Интерфейс должен обеспечивать нумерацию элементов вектора, начиная с 1 и заканчивая n.




Слайд 105


5. Объектно-ориентированное программирование 5.6. Перегрузка операций
template
class CVecn
{

double m_array [Size];
public:
CVecn (void) {for (int i=0; i<=Size-1; i++) m_array[i]=0;}
~CVecn (void) {}

CVecn operator -();
CVecn operator +(CVecn r);
CVecn operator -(CVecn r);
double operator *(CVecn r);

CVecn operator *(double r);
friend CVecn operator *(double l, CVecn r)
{for (int i=0; i<=Size-1; i++) r.m_array[i]*=l; return r;}

bool operator ==(CVecn r);
bool operator !=(CVecn r);

double& operator [] (int i);
};


Слайд 106


5. Объектно-ориентированное программирование 5.8. Перегрузка операций
Унарные операторы
Могут быть перегружены как

нестатические члены класса без параметров:
Имя_Типа operator @ ( );

здесь @ обозначает один из следующих унарных операторов:
& * + - ~ !



CVecn operator - ();

template
CVecn CVecn ::operator -()
{
for (int i=0; i<=Size-1; i++) m_array[i]=-m_array[i];
return *this;
}


Слайд 107


5. Объектно-ориентированное программирование 5.8. Перегрузка операций
Унарные операторы
Или могут быть перегружены

как (дружественные) функции не члены класса с одним параметром:
Имя_Типа operator @ (параметр);

здесь @ обозначает один из следующих унарных операторов:
& * + - ~ !



friend CVecn operator - (CVecn r)
{
for (int i=0; i<=Size-1; i++) r.m_array[i]=-m_array[i];
return *this;
}

Внимание! Если дружественная функция объявляется для шаблона класса и ее аргументами являются специализации шаблона, то определение этой функции должно находиться внутри класса!!!


Слайд 108


5. Объектно-ориентированное программирование 5.8. Перегрузка операций
Оператор присваивания
Оператор присваивания может быть

перегружен только как нестатический член класса и должен иметь следующий прототип:
Имя_Класса& operator = (const Имя_Класса &Имя_Параметра);

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


Слайд 109


5. Объектно-ориентированное программирование 5.6. Перегрузка операций
Оператор присваивания
Оператор присваивания может быть

перегружен только как нестатический член класса и должен иметь следующий прототип:
Имя_Класса& operator = (const Имя_Класса &Имя_Параметра);

В нашем случае переопределять оператор присваивания не надо. В принципе, это можно было сделать так:

CVecn& operator = (const CVecn& r);

template
CVecn & CVecn ::operator =(const CVecn &r )
{
if (&r !=this) for (int i=0; i<=Size-1; i++) m_array[i]=r.m_array[i];
return *this;
}


Слайд 110


5. Объектно-ориентированное программирование 5.6. Перегрузка операций
Оператор индексирования
Оператор индексирования может быть

перегружен только как нестатический член класса с одним параметром – значением индекса:
Имя_Типа& operator [] = (const int& i);

double& operator [ ] (const int &i);

template
double& CVecn ::operator [](const int& i)
{
if (i<1) return m_array [0];
if (i>Size) return m_array [Size-1];
return m_array [i-1];
}


Слайд 111


5. Объектно-ориентированное программирование 5.6. Перегрузка операций
Бинарные операторы
Бинарные операторы могут быть

перегружены как нестатические члены класса с одним параметром – значением второго (правого операнда:
Имя_Типа operator @ (Тип_Параметра Имя_Параметра);

здесь @ обозначает один из следующих бинарных операторов:
+ - * / % == <= >= != && || << >>

CVecn operator +(CVecn r);

template
CVecn CVecn ::operator +(CVecn r)
{
for (int i=0; i<=Size-1; i++) m_array[i]+=r.m_array[i];
return *this;
}


Слайд 112


5. Объектно-ориентированное программирование 5.8. Перегрузка операций
Бинарные операторы
Бинарные операторы могут быть

перегружены как нестатические члены класса с одним параметром – значением второго (правого операнда:
Имя_Типа operator @ (Тип_Параметра Имя_Параметра);

здесь @ обозначает один из следующих бинарных операторов:
+ - * / % == <= >= != && || << >>

CVecn operator -(CVecn r);

template
CVecn CVecn ::operator -(CVecn r)
{
for (int i=0; i<=Size-1; i++) m_array[i]-=r.m_array[i];
return *this;
}


Слайд 113


5. Объектно-ориентированное программирование 5.8. Перегрузка операций
double operator * (CVecn r);


CVecn operator * (double r);

template
double CVecn ::operator *(CVecn r)
{
double s=0;
for (int i=0; i<=Size-1; i++) s+=m_array[i]*m_array[i];
return s;
}

template
CVecn CVecn ::operator *(double r)
{
for (int i=0; i<=Size-1; i++) m_array[i]*=r;
return *this;
}

Слайд 114


5. Объектно-ориентированное программирование 5.8. Перегрузка операций
bool operator ==(CVecn r);
bool operator

!=(CVecn r);

template
bool CVecn ::operator ==(CVecn r)
{
for (int i=0; i<=Size-1; i++) if (m_array[i] != r.m_array[i]) return false;
return true;
}

template
bool CVecn ::operator !=(CVecn r)
{
for (int i=0; i<=Size-1; i++)if (m_array[i] != r.m_array[i])return true;
return false;
}

Слайд 115


5. Объектно-ориентированное программирование 5.6. Перегрузка операций
Бинарные операторы
Бинарные операторы также могут

быть перегружены как не члены класса с двумя параметрами – левым и правым операндами:
Имя_Типа operator @ (Тип_Пар Имя_Пар, Тип_Пар Имя_Пар );

здесь @ обозначает один из следующих бинарных операторов:
+ - * / % == <= >= != && || << >>

friend CVecn operator *(double l, CVecn r)
{for (int i=0; i<=Size-1; i++) r.m_array[i] *= l; return r;}

Внимание! Если дружественная функция объявляется для шаблона класса и ее аргументами являются специализации шаблона, то определение этой функции должно находиться внутри класса!!!


Слайд 116


5. Объектно-ориентированное программирование 5.6. Перегрузка операций
Перегрузка других операторов
Составные операторы присваивания

(+= -= *= /=) могут быть перегружены как нестатические члены класса:
Имя_Класса& operator @ (const Имя_Класса& Имя_Параметра );

Операторы инкремента ++ и декремента -- могут быть перегружены как члены класса без аргументов или как не члены класса с одним аргументом. Для того, чтобы префиксные операторы отличать от постфиксных, в объявлении последних вводят дополнительный фиктивный параметр типа int .
Имя_Класса operator @ (); //префиксный
Имя_Класса operator @ (int); //постфиксный

Имя_Класса operator @ (Имя_Класса& Имя_Параметра );
Имя_Класса operator @ (Имя_Класса& Имя_Параметра ,int);



Слайд 117


5. Объектно-ориентированное программирование 5.6. Перегрузка операций
Перегрузка других операторов
Оператор вызова функции

( ) может быть перегружен только как нестатический члены класса:
Имя_Типа operator @ (список_параметров);

Здесь количество параметров может быть произвольным, и допускается определять значения параметров по умолчанию. Вызывается оператор вызова функции путем применения списка фактических параметров к объекту класса, в котором он определен. Так как в этом случае объект может использоваться как функция, он иногда называется функциональным объектом.
Операторы преобразования типа (конвертер) –функция-член класса, которая преобразует тип объекта класса в некоторый другой тип. Конвертор имеет следующий прототип:
operator Имя_Типа ();

Здесь Имя_Типа задает тип данных (встроенный или пользовательский), к которому приводится объект. Конвертер может вызываться как явно, так и неявно – при преобразованиях типов в выражениях, вызове функций и т.п.



Слайд 118


5. Объектно-ориентированное программирование 5.8. Перегрузка операций
Перегрузка других операторов
Перегруженные операторы >>

и << для ввода и вывода. Для перегрузки определяются как дружественные операторы класса, которые имеют следующие прототипы:
friend istream& operator >> (istream&, Имя_Класса& Имя_параметра);
friend ostream& operator << (ostream&, const Имя_Класса& Имя_параметра);

Примеры перегрузки операторов, не рассмотренных подробно в настоящем разделе будут приведены в разделе «Абстрактные типы данных»
Перегрузку операторов new, delete, доступа к классам предлагается рассмотреть, при необходимости, самостоятельно.

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

Слайд 119


5. Объектно-ориентированное программирование 5.8. Перегрузка операций
Вернемся еще раз к описанию


шаблона класса CVecn

template
class CVecn
{
double m_array [Size];
public:
CVecn (void) {for (int i=0; i<=Size-1; i++) m_array[i]=0;}
~CVecn (void) {}

CVecn operator -();
CVecn operator +(CVecn r);
CVecn operator -(CVecn r);
double operator *(CVecn r);

CVecn operator *(double r);
friend CVecn operator *(double l, CVecn r)
{for (int i=0; i<=Size-1; i++) r.m_array[i]*=l; return r;}

bool operator ==(CVecn r);
bool operator !=(CVecn r);

double& operator [] (int i);
};


Слайд 120template
CVecn CVecn ::operator - ()
{
for

(int i=0; i<=Size-1; i++) m_array[i]=-m_array[i];
return *this;
}

template
CVecn CVecn ::operator +(CVecn r)
{
for (int i=0; i<=Size-1; i++) m_array[i]+=r.m_array[i];
return *this;
}

template
CVecn CVecn ::operator -(CVecn r)
{
for (int i=0; i<=Size-1; i++) m_array[i]-=r.m_array[i];
return *this;
}





5. Объектно-ориентированное программирование 5.8. Перегрузка операций

Определения функций
(так как это шаблон –
все размещаем
в одном файле)


Слайд 121
template
double CVecn ::operator *(CVecn r)
{
double s=0;

for (int i=0; i<=Size-1; i++) s+=m_array[i]*m_array[i];
return s;
}

template
CVecn CVecn ::operator *(double r)
{
for (int i=0; i<=Size-1; i++) m_array[i]*=r;
return *this;
}




5. Объектно-ориентированное программирование 5.6. Перегрузка операций

Определения функций


Слайд 122template
bool CVecn ::operator ==(CVecn r)
{
for (int i=0;

i<=Size-1; i++)if (m_array[i]!=r.m_array[i])return false;
return true;
}

template
bool CVecn ::operator !=(CVecn r)
{
for (int i=0; i<=Size-1; i++)if (m_array[i]!=r.m_array[i])return true;
return false;
}

template
double& CVecn ::operator [](const int& i)
{
if (i<1) return m_array[0];
if (i>Size) return m_array[Size-1];
return m_array[i-1];
}




5. Объектно-ориентированное программирование 5.6. Перегрузка операций

Определения функций


Слайд 123int main()
{
const int n=5;
CVecn v1;

v1[1]=1; v1[2]=2; v1[3]=3; v1[4]=4; v1[5]=10;
CVecn v2=v1;

v2[1]=0;
v1=v2;
cout << endl; for (int i=1; i<=n; i++)cout << v1[i]<<" ";

v1*5;
cout << endl; for (int i=1; i<=n; i++)cout << v1[i]<<" ";

v1+v2;
cout << endl; for (int i=1; i<=n; i++)cout << v1[i]<<" ";

return 0;
}




5. Объектно-ориентированное программирование 5.8. Перегрузка операций

Пример программы, использующей класс CVecn

Операции сложения и вычитания векторов, умножения вектора на скаляр, изменения знака выполняются «на месте»: результат сохраняется в первом операнде


Слайд 124template
class CVecn
{
double m_array [Size];
public:
CVecn

(void) {for (int i=0; i<=Size-1; i++) m_array[i]=0;}
~CVecn (void) {}

CVecn operator -();
CVecn operator +(CVecn r);
CVecn operator -(CVecn r);
double operator *(CVecn r);

CVecn operator *(double r);
friend CVecn operator *(double l, CVecn r)
{for (int i=0; i<=Size-1; i++) r.m_array[i]*=l; return r;}

bool operator ==(CVecn r);
bool operator !=(CVecn r);

double& operator [] (int i);
};




5. Объектно-ориентированное программирование 5.8. Перегрузка операций

В третий раз вернемся к описанию шаблона класса CVecn

Обратите внимание: то, каким образом реализован n-мерный вектор, отделено от пользователя интерфейсом как стеной. Здесь даже нет ни одной функции для доступа к полям (типа Set или Get.

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


Слайд 125


Абстрактный тип данных (АТД – abstract data type) – это множество

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

5. Объектно-ориентированное программирование 5.9. Абстрактные типы данных

Программа










Интерфейс

Структура данных





Добавить

Удалить

Найти

Отобразить


Запрос на выполнение операции

Результат выполнения операции


Слайд 126
Разработка абстрактных моделей для данных и способов обработки этих данных –

важнейший этап решения задач с помощью ЭВМ.
С помощью АТД мы представляем данные, которые используются в реальном мире и при построении математических моделей, в виде структур данных, которые могут быть созданы средствами языка программирования.
Создание АТД предполагает полное сокрытие реализации АТД в виде структур данных от пользователя.
Set – Get стиль доступа к АТД карается расстрелом!!!
Реализация АТД предполагает расширение понятия операции над значениями типа данных с помощью интерфейсных процедур и функций. Важный инструмент, позволяющий добиться определения операций над АТД – перегрузка операций.
Рассмотрим в качестве примера абстрактного типа данных комплексные числа.




5. Объектно-ориентированное программирование 5.7. Абстрактные типы данных


Слайд 127

5. Объектно-ориентированное программирование 5.9. Абстрактные типы данных
class CCmplx // file

Cmplx.h
{
double m_re;
double m_im;

public:
CCmplx(double re=0, double im=0):m_re(re), m_im(im){} //CCmplx z1(1,0), z2; z2=CCmplx(1,1);
~CCmplx(void){}

// функции для взятия вещественной и мнимой части можно определить так:
double &Re() {return m_re;} // z1.Re()=5;
double &Im() {return m_im;} // double r1=z1.Im();

// и одновременно так:
friend double& Re(CCmplx &z){return z.m_re;} // Re(z1)=5;
friend double& Im(CCmplx &z){return z.m_im;} // double r1=Im(z1);

// или переопределить для этого оператор [ ]
double& operator [ ] (int i){if (i<=1)return m_re; else return m_im;} // z1[1] = z2[2]




Слайд 128

5. Объектно-ориентированное программирование 5.9. Абстрактные типы данных
// file Cmplx.h (continuation)

//

этот оператор присваивания перегружать необязательно:
// CCmplx& operator = (CCmplx z) {if (&z !=this) {m_re=z.m_re; m_im=z.m_im; return *this;}}

// если хотим присваивать комплексному double надо перегрузить так:
CCmplx& operator = (double r){m_re=r; m_im=0; return *this;} // z1=5;

//Функциональный объект (перегрузка оператора вызова функции)
CCmplx& operator () (double x=0, double y=0) {m_re=x; m_im=y; return *this;} // z2(1,3); z1=z2(2,2)

// Конвертер из CCmplx в double (вызывается явно или неявно)
operator double (){return m_re;} // r1= z1; r1 =double(z2); r1= static_cast (z1);

// Некорректное переопределение унарного -
// CCmplx operator -(){m_re=-m_re; m_im=-m_im; return *this;} // z2=-z1 – изменится знак z1 !!!

// Корректно сделать так:
CCmplx operator - (){return CCmplx(-m_re, -m_im);} // правильно
CCmplx operator + (){return *this;} // здесь можно оставить и так



Слайд 129

5. Объектно-ориентированное программирование 5.9. Абстрактные типы данных
// file Cmplx.h (continuation)

CCmplx operator ++ () {++m_re; return *this;} // prefix z1=++z2;
CCmplx operator ++ (int) {m_re++; return *this;} //postfix z1=z2++; (выполняется как prefix)

CCmplx operator +(CCmplx z) {return CCmplx (m_re+z.m_re, m_im+z.m_im);} // z3=z1+z2;
CCmplx operator - (CCmplx z) {return CCmplx (m_re-z.m_re, m_im-z.m_im); } // z3=z1+z2;
CCmplx operator * (CCmplx z); // z3=z1*z2;
CCmplx operator / (CCmplx z); //z3=z1/z2;

CCmplx CCmplx::operator *(CCmplx z) // file Cmplx.cpp
{
return CCmplx (m_re*z.m_re - m_im*z.m_im, m_re*z.m_im + m_im*z.m_im);
}


CCmplx CCmplx::operator /(CCmplx z)
{
double d=z.m_re*z.m_re + z.m_im*z.m_im;
return CCmplx((m_re*z.m_re+m_im*z.m_im)/d, (m_im*z.m_re+m_re*z.m_im)/d);
}


Слайд 130

5. Объектно-ориентированное программирование 5.7. Абстрактные типы данных
// file Cmplx.h

(continuation)

CCmplx operator + (double r) {return CCmplx (m_re+r, m_im);} // z2=z1+r1;
CCmplx operator - (double r) {return CCmplx (m_re-r, m_im);} // z2=z1-r1;
CCmplx operator * (double r) {return CCmplx (m_re*r, m_im*r);} // z2=z1*r1;
CCmplx operator / (double r) {return CCmplx (m_re/r, m_im/r);} // z2=z1/r1;

// Можно так:
// CCmplx operator +=(CCmplx r) {m_re += r.m_re; m_im += r.m_im; return *this;} // z1+=z2;

// Красивее использовать ранее переопределенные арифметические операторы
CCmplx operator += (CCmplx z) {return (*this = *this + z); } // z1+=z2;
CCmplx operator -= (CCmplx z) {return (*this = *this - z) ; } // z1-=z2;
CCmplx operator *= (CCmplx z); {return (*this = *this * z) ; } // z1*=z2;
CCmplx operator /= (CCmplx z); {return (*this = *this / z) ; } // z1/=z2;

CCmplx operator += (double r) {m_re+=r; return *this;} // z1+=r1;
CCmplx operator -= (double r) {m_re-=r; return *this;} // z1-=r2;
CCmplx operator *= (double r) {m_re*=r; m_im*=r; return *this;} // z1*=r2;
CCmplx operator /= (double r) {m_re/=r; m_im/=r; return *this;} // z1/=r2;

Слайд 131

5. Объектно-ориентированное программирование 5.9. Абстрактные типы данных
// file Cmplx.h (continuation)



bool operator ==(CCmplx z) {return (m_re==z.m_re)&&(m_im==z.m_im)?true:false;}
bool operator != (CCmplx z) {return (m_re!==z.m_re)||(m_im!=z.m_im)?true:false;}
bool operator ==(double r) {return (m_re==r)&&(m_im==0)?true:false;}
bool operator != (double r) {return (m_re!=r)||(m_im!=0)?true:false;}



Слайд 132

5. Объектно-ориентированное программирование 5.9. Абстрактные типы данных
// file Cmplx.h (continuation)


friend CCmplx operator + (double r, CCmplx z ) {return (z+r);} //z1=5+z2;
friend CCmplx operator - (double r, CCmplx z ); //z1=r1-z2;
friend CCmplx operator * (double r, CCmplx z ) {return (z*r);} //z1=r1*z2
friend CCmplx operator / (double r, CCmplx z ); //z1=r1/z2

// file Cmplx.cpp
// Дружественные функции не являются членами класса CCmplx
// (их заголовку в реализации не предшествует конструкция CCmplx::

CCmplx operator -(double r, CCmplx z ){return CCmplx(r-z.m_re, -z.m_im);}
CCmplx operator / (double r, CCmplx z ){return(CCmplx(r,0)/z);}

Только работать это не будет из-за наличия конвертора из ССmplx в double. Модуль CCmplx скомпилируется, но как только в Вашей программе появится оператор z1 = 5 + z2, компилятор не будет знать, что делать:
а) сконвертировать z2 в double, сложить 5 и то, что получилось при конвертации, присвоить результат z1 (в результате потеряем мнимую часть);
б) использовать перегруженный здесь +.
На этапе компиляции программы будет выдано сообщение об ошибке. Разумно избавиться от конвертора: operator double (){return m_re;}


Слайд 133

5. Объектно-ориентированное программирование 5.9. Абстрактные типы данных
// file Cmplx.h (continuation)


friend double operator +=(double &r, CCmplx z ); ` //r1 += z1;
friend double operator -=(double &r, CCmplx z ); //r1 -= z1;
friend double operator *=(double &r, CCmplx z ); //r1 *= z1;
friend double operator /=(double &r, CCmplx z ); //r1 /= z1;

friend bool operator ==(double r, CCmplx z);
friend bool operator !=(double r, CCmplx z);


double operator +=(double &r, CCmplx z ){r=r+z.m_re; return r;} // file Cmplx.cpp
double operator -=(double &r, CCmplx z ){r=r-z.m_re; return r;}
double operator *=(double &r, CCmplx z ){r=r*z.m_re; return r;};
double operator /=(double &r, CCmplx z ){z=r/z; r=z.Re(); return r;} //z передаем по значению!!!

bool operator ==(double l, CCmplx r){return (r.m_re=l)&&(r.m_im=0)?true:false;}
bool operator !=(double l, CCmplx r){return (r.m_re!=l)||(r.m_im!=0)?true:false;}


Слайд 134

5. Объектно-ориентированное программирование 5.7. Абстрактные типы данных
// file Cmplx.h (continuation)


friend std::istream& operator >> (std::istream &str, CCmplx &r);
friend std::ostream& operator << (std::ostream& str, CCmplx r);
};

std::istream& operator >> (std::istream &str, CCmplx &z) // file Cmplx.cpp
{
double re=0, im=0; str>>re>>im; z=CCmplx(re,im); return str;
}

std::ostream& operator << (std::ostream& str, CCmplx z)
{
if (z.m_im<0)return str< else return str<}


Обратная связь

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

Email: Нажмите что бы посмотреть 

Что такое ThePresentation.ru?

Это сайт презентаций, докладов, проектов, шаблонов в формате PowerPoint. Мы помогаем школьникам, студентам, учителям, преподавателям хранить и обмениваться учебными материалами с другими пользователями.


Для правообладателей

Яндекс.Метрика