Скачать презентацию Программирование на С Тема 1 2 Классы и Скачать презентацию Программирование на С Тема 1 2 Классы и

Качесова Л.Ю.-Прогр.2--20130212085151.ppt

  • Количество слайдов: 37

Программирование на С++ Тема 1. 2 Классы и объекты 16. 02. 2018 1 Программирование на С++ Тема 1. 2 Классы и объекты 16. 02. 2018 1

Передача объектов в функции • Пример 1. Передача объектов по значению #include <iostream> #include Передача объектов в функции • Пример 1. Передача объектов по значению #include #include using namespace std; class Distance // Класс английских мер длины { private: int feet; // футы float inches; // дюймы public: Distance(): feet(0), inches(0. 0){} Distance(int ft, float in): feet(ft), inches(in){} void getdist(); void showdist(); //сложение двух длин void add_dist(Distance d 1, Distance d 2); }; 16. 02. 2018 2

> feet; cout <<" src="https://present5.com/presentation/34257183_156078422/image-3.jpg" alt="void Distance: : getdist() {cout << "nvvod feet: "; cin >> feet; cout <<" /> void Distance: : getdist() {cout << "nvvod feet: "; cin >> feet; cout << "vvod inches: "; cin >> inches; } void Distance: : showdist() { cout << feet << "'-" << inches << '"'; } void Distance: : add_dist(Distance d 1, Distance d 2) {inches = d 1. inches + d 2. inches; //сложение дюймов feet = 0; //с возможным заемом if (inches >= 12. 0) { inches -= 12. 0; // уменьшаем дюймы на 12 feet++; } // и увеличиваем футы на 1 feet += d 1. feet + d 2. feet; // сложение футов } 16. 02. 2018 3

int main() { Distance dist 1, dist 3; dist 1. getdist(); Distance dist 2(11, int main() { Distance dist 1, dist 3; dist 1. getdist(); Distance dist 2(11, 6. 25); dist 3. add_dist(dist 1, dist 2); cout << "ndist 1 = "; dist 1. showdist(); cout << endl; cout << "dist 2 = "; dist 2. showdist(); cout << endl; cout << "dist 3 = "; dist 3. showdist(); cout << endl; getch(); } 16. 02. 2018 4

Ø Синтаксически объекты передаются в функции так же, как и переменные других типов. Для Ø Синтаксически объекты передаются в функции так же, как и переменные других типов. Для этого объявляют параметр функции, который имеет тип класса. Затем используют объект этого класса в качестве аргумента при вызове функции. По умолчанию происходит передача объекта по значению. Ø При передаче объекта в функцию по значению создается копия этого объекта. При завершении работы функции созданная копия объекта удаляется. При вызове функции, в момент создания копии объекта, обычный конструктор не вызывается, так как он используется для инициализации элементов объекта, а копия создается для уже существующего (а значит – проинициализированного) объекта. Вызывается конструктор копирования. Ø Но при завершении работы функции, т. е. при удалении копии объекта, вызывается деструктор, так как иначе могут оказаться невыполненными некоторые необходимые действия, связанные с его удалением, например освобождение памяти. Ø Здесь возникает проблема освобождения динамической памяти. Ø Поскольку объект и его копия, если они содержат указатели, обращаются к одной и той же области памяти, то все изменения, производимые с этой памятью копией, будут влиять на объект-оригинал. Кроме того, освобождение памяти деструктором копии приводит к тому, что указатель объекта может стать неопределенным. Ø Одним из способов обойти эту проблему является передача объектов в функцию по указателю (по ссылке) , другой способ программировать конструктор копирования. Ø При передаче объекта в функцию по указателю происходит передача его адреса, а не значения. При этом функция может изменять значение объекта, используемого в вызове. Ø Ссылка является скрытым указателем и всегда работает просто как другое имя переменной. При передаче параметра по ссылке изменения объекта внутри функции влияют на исходный объект и сохраняются при завершении работы функции. Ø Ссылка не является аналогом указателя, поэтому при передаче объекта по ссылке для доступа к его элементам используется операция «точка » (. ), а не «стрелка» (->). 16. 02. 2018 5

 • Пример 2. Передача объектов по указателю #include <iostream> #include <conio. h> using • Пример 2. Передача объектов по указателю #include #include using namespace std; class Distance // Класс английских мер длины { private: int feet; // футы float inches; // дюймы public: Distance(): feet(0), inches(0. 0){} Distance(int ft, float in): feet(ft), inches(in){} void getdist(); void showdist(); //сложение двух длин void add_dist(Distance *d 1, Distance *d 2); }; 16. 02. 2018 6

> feet; cout <<" src="https://present5.com/presentation/34257183_156078422/image-7.jpg" alt="void Distance: : getdist() {cout << "nvvod feet: "; cin >> feet; cout <<" /> void Distance: : getdist() {cout << "nvvod feet: "; cin >> feet; cout << "vvod inches: "; cin >> inches; } void Distance: : showdist() { cout << feet << "'-" << inches << '"'; } void Distance: : add_dist(Distance *d 1, Distance *d 2) {inches = d 1 ->inches + d 2 ->inches; //сложение дюймов feet = 0; //с возможным заемом if (inches >= 12. 0) { inches -= 12. 0; // уменьшаем дюймы на 12 feet++; } // и увеличиваем футы на 1 feet += d 1 ->feet + d 2 ->feet; // сложение футов } 16. 02. 2018 7

int main() { Distance dist 1, dist 3; dist 1. getdist(); Distance dist 2(11, int main() { Distance dist 1, dist 3; dist 1. getdist(); Distance dist 2(11, 6. 25); dist 3. add_dist(&dist 1, &dist 2); cout << "ndist 1 = "; dist 1. showdist(); cout << endl; cout << "dist 2 = "; dist 2. showdist(); cout << endl; cout << "dist 3 = "; dist 3. showdist(); cout << endl; getch(); } 16. 02. 2018 8

 • Пример 3. Передача объектов по ссылке #include <iostream> #include <conio. h> using • Пример 3. Передача объектов по ссылке #include #include using namespace std; class Distance // Класс английских мер длины { private: int feet; // футы float inches; // дюймы public: Distance(): feet(0), inches(0. 0){} Distance(int ft, float in): feet(ft), inches(in){} void getdist(); void showdist(); //сложение двух длин void add_dist(Distance &d 1, Distance &d 2); }; 16. 02. 2018 9

> feet; cout <<" src="https://present5.com/presentation/34257183_156078422/image-10.jpg" alt="void Distance: : getdist() {cout << "nvvod feet: "; cin >> feet; cout <<" /> void Distance: : getdist() {cout << "nvvod feet: "; cin >> feet; cout << "vvod inches: "; cin >> inches; } void Distance: : showdist() { cout << feet << "'-" << inches << '"'; } void Distance: : add_dist(Distance &d 1, Distance &d 2) {inches = d 1. inches + d 2. inches; //сложение дюймов feet = 0; //с возможным заемом if (inches >= 12. 0) { inches -= 12. 0; // уменьшаем дюймы на 12 feet++; } // и увеличиваем футы на 1 feet += d 1. feet + d 2. feet; // сложение футов } 16. 02. 2018 10

int main() { Distance dist 1, dist 3; dist 1. getdist(); Distance dist 2(11, int main() { Distance dist 1, dist 3; dist 1. getdist(); Distance dist 2(11, 6. 25); dist 3. add_dist(dist 1, dist 2); cout << "ndist 1 = "; dist 1. showdist(); cout << endl; cout << "dist 2 = "; dist 2. showdist(); cout << endl; cout << "dist 3 = "; dist 3. showdist(); cout << endl; getch(); } 16. 02. 2018 11

 • Пример 4. Объект в качестве возвращаемого значения #include <iostream> #include <conio. h> • Пример 4. Объект в качестве возвращаемого значения #include #include using namespace std; class Distance // Класс английских мер длины { private: int feet; // футы float inches; // дюймы public: Distance(): feet(0), inches(0. 0){} Distance(int ft, float in): feet(ft), inches(in){} void getdist(); void showdist(); //сложение двух длин Distance add_dist(Distance d 2); }; 16. 02. 2018 12

> feet; cout <<" src="https://present5.com/presentation/34257183_156078422/image-13.jpg" alt="void Distance: : getdist() {cout << "nvvod feet: "; cin >> feet; cout <<" /> void Distance: : getdist() {cout << "nvvod feet: "; cin >> feet; cout << "vvod inches: "; cin >> inches; } void Distance: : showdist() { cout << feet << "'-" << inches << '"'; } Distance: : add_dist(Distance d 2) {int f = feet +d 2. feet; // складываем футы float i = inches +d 2. inches; //складываем дюймы if (i >= 12. 0) { i-=12. 0; // уменьшаем дюймы на 12 f++; } // и увеличиваем футы на 1 Distance D(f, i) //создаем и return D; // возвращаем временный объект } 13

int main() { Distance dist 1, dist 3; dist 1. getdist(); Distance dist 2(11, int main() { Distance dist 1, dist 3; dist 1. getdist(); Distance dist 2(11, 6. 25); dist 3 = dist 1. add_dist(dist 2); cout << "ndist 1 = "; dist 1. showdist(); cout << endl; cout << "dist 2 = "; dist 2. showdist(); cout << endl; cout << "dist 3 = "; dist 3. showdist(); cout << endl; getch(); } 16. 02. 2018 14

Ø Ø Для того чтобы функция могла возвращать объект, нужно объявить ее так, чтобы Ø Ø Для того чтобы функция могла возвращать объект, нужно объявить ее так, чтобы ее возвращаемое значение имело тип класса, а затем поставить объект этого типа в операторе return. Когда функция возвращает объект, для его хранения автоматически создается временный объект. После того как значение возвращено, этот временный объект удаляется. Если возвращаемый объект содержит указатели, то удаление его временной копии может привести к неожиданным и печальным последствиям, связанным с особенностями вызова конструктора и деструктора, поэтому необходимо программировать конструктор копирования. 16. 02. 2018 15

Дружественные функции • Синтаксис объявления дружественных функций: class имя_класса { friend тип имя_другого_класса: : Дружественные функции • Синтаксис объявления дружественных функций: class имя_класса { friend тип имя_другого_класса: : имя_функции(список параметров); friend тип имя_функции(список параметров); } 16. 02. 2018 16

Ø Дружественные функции, не являясь элементами класса, имеют доступ к его закрытым и защищенным Ø Дружественные функции, не являясь элементами класса, имеют доступ к его закрытым и защищенным элементам. Для того чтобы объявить функцию дружественной некоторому классу, нужно в этот класс включить ее прототип, перед которым поставить ключевое слово friend. Ø Дружественная классу функция может быть методом другого класса, или не принадлежать ни к какому классу. Ø Можно объявить целый класс дружественным данному классу, включив в определение этого класса описание другого класса с ключевым словом friend. Тогда всем элементам дружественного класса будет разрешен доступ ко всем элементам того класса, для которого он объявлен дружественным. Ø Так как дружественная функция не является членом того класса, для которого она дружественна, то ее нельзя вызвать, используя имя объекта. Ø Доступ дружественной функции к закрытым элементам класса можно осуществить только через объект класса, который объявлен у нее внутри или передан ей. 16. 02. 2018 17

 • Пример. Использование дружественной функции #include <iostream> #include <conio. h> using namespace std; • Пример. Использование дружественной функции #include #include using namespace std; class Distance // Класс английских мер длины { private: int feet; // футы float inches; // дюймы public: Distance(): feet(0), inches(0. 0){} Distance(int ft, float in): feet(ft), inches(in){} void getdist(); void showdist(); //сложение двух длин friend Distance add_dist(Distance d 1, Distance d 2); }; 16. 02. 2018 18

> feet; cout <<" src="https://present5.com/presentation/34257183_156078422/image-19.jpg" alt="void Distance: : getdist() {cout << "nvvod feet: "; cin >> feet; cout <<" /> void Distance: : getdist() {cout << "nvvod feet: "; cin >> feet; cout << "vvod inches: "; cin >> inches; } void Distance: : showdist() { cout << feet << "'-" << inches << '"'; } Distance add_dist(Distance d 1, Distance d 2) {Distance t; t. inches = d 1. inches + d 2. inches; //сложение дюймов t. feet = 0; //с возможным заемом if (t. inches >= 12. 0) { t. inches -= 12. 0; // уменьшаем дюймы на 12 t. feet++; } // и увеличиваем футы на 1 t. feet += d 1. feet + d 2. feet; // сложение футов return t; } 16. 02. 2018 19

int main() { Distance dist 1, dist 3; dist 1. getdist(); Distance dist 2(11, int main() { Distance dist 1, dist 3; dist 1. getdist(); Distance dist 2(11, 6. 25); dist 3=add_dist(dist 1, dist 2); cout << "ndist 1 = "; dist 1. showdist(); cout << endl; cout << "dist 2 = "; dist 2. showdist(); cout << endl; cout << "dist 3 = "; dist 3. showdist(); cout << endl; getch(); } 16. 02. 2018 20

Перегрузка операций • Синтаксис описания операторной функции: тип operator # (список параметров) { выполняемые Перегрузка операций • Синтаксис описания операторной функции: тип operator # (список параметров) { выполняемые действия } , # - знак перегружаемой операции. Операции: . , : : , ? : , sizeof - перегружать нельзя; 16. 02. 2018 21

Ø Язык С++ располагает рядом встроенных типов данных, включая int, float, char и т. Ø Язык С++ располагает рядом встроенных типов данных, включая int, float, char и т. д. Для работы с данными этих типов используются встроенные операции, например, сложение (+) и умножение (*). Кроме того, язык С++ позволяет добавлять и перегружать подобные операции для работы с объектами пользовательских классов. Ø Для перегрузки операции создается операторная функция. Ø Операторная функция может быть методом класса или дружественной функцией. Ø Существует несколько ограничений на перегрузку операций: Ø Операции: . , : : , ? : , sizeof - перегружать нельзя; Ø Нельзя изменить приоритет операций; Ø Нельзя менять число операндов операции; Ø Нельзя создавать новые операции, можно перегружать только существующие; Ø Операторная функция не может иметь параметров, передаваемых по умолчанию. 16. 02. 2018 22

Перегрузка бинарных операций Ø Синтаксис определения операторной функции - метода: тип имя_класса : : Перегрузка бинарных операций Ø Синтаксис определения операторной функции - метода: тип имя_класса : : operator знак операции (описание параметра) { операторы, определяющие действие операции } Ø Синтаксис определения операторной функции - друга: friend тип operator знак операции (описание параметров) { операторы, определяющие действие операции } 16. 02. 2018 23

Перегрузка унарных операций Ø Синтаксис определения операторной функции - метода: тип имя_класса : : Перегрузка унарных операций Ø Синтаксис определения операторной функции - метода: тип имя_класса : : operator знак операции ( ) { операторы, определяющие действие операции } Ø Синтаксис определения операторной функции - друга: friend тип operator знак операции (описание параметра) { операторы, определяющие действие операции } 16. 02. 2018 24

Ø При перегрузке бинарной операции с использованием операторной функции - метода ей передается явным Ø При перегрузке бинарной операции с использованием операторной функции - метода ей передается явным образом только один аргумент – объект, располагаемый с правой стороны от символа операции. Второй же аргумент (объект, располагаемый с левой стороны от символа операции) передается неявно через указатель this. Ø Тип значения, возвращаемого заданной операцией часто совпадает с именем класса, для которого перегружается данная операция – это облегчает использование перегруженной операции в составных выражениях. Ø Функции – «друзья» не имеют указателя this, поэтому, если для перегрузки бинарной операции используется функция – «друг» ей явным образом передаются два операнда. Ø Среди всех операций особое место в контексте перегрузки занимает операция присваивания. В отличие от всех остальных операций, если для класса нет явного ее определения, то она автоматически генерируется компилятором. Такая по умолчанию созданная операция присваивания производит битовую копию объекта. Если для объектов недостаточно простого побитового копирования (например, для объектов, содержащих динамические поля), то необходимо явно перегрузить операцию присваивания. Ø При перегрузке унарной операции с помощью операторной функции - метода - ни один объект не передается явным образом. Операция же выполняется над объектом, который генерирует вызов этой функции через неявно переданный указатель this. Ø При перегрузке унарной операции с помощью операторной функции – «друга» - операторной функции передается один операнд. 16. 02. 2018 25

Пример перегрузки бинарной операции + (с использованием операторной функции-метода) #include <iostream> #include <conio. h> Пример перегрузки бинарной операции + (с использованием операторной функции-метода) #include #include using namespace std; class Distance // Класс английских мер длины { private: int feet; // футы float inches; // дюймы public: Distance(): feet(0), inches(0. 0){} Distance(int ft, float in): feet(ft), inches(in){} void getdist(); void showdist(); //сложение двух длин Distance operator+(Distance d 2); }; 16. 02. 2018 26

> feet; cout <<" src="https://present5.com/presentation/34257183_156078422/image-27.jpg" alt="void Distance: : getdist() {cout << "nvvod feet: "; cin >> feet; cout <<" /> void Distance: : getdist() {cout << "nvvod feet: "; cin >> feet; cout << "vvod inches: "; cin >> inches; } void Distance: : showdist() { cout << feet << "'-" << inches << '"'; } Distance: : operator+(Distance d 2) { int f = feet + d 2. feet; // складываем футы float i = inches + d 2. inches; //складываем // дюймы if (i >= 12. 0) { i-=12. 0; // уменьшаем дюймы на 12 f++; } // и увеличиваем футы на 1 return Distance(f, i); //создаем и возвращаем // временный объект } 16. 02. 2018 27

int main () { Distance dist 1, dist 3; dist 1. getdist(); Distance dist int main () { Distance dist 1, dist 3; dist 1. getdist(); Distance dist 2(11, 6. 25); dist 3 = dist 1+ dist 2; cout << "ndist 1 = "; dist 1. showdist(); cout << endl; cout << "dist 2 = "; dist 2. showdist(); cout << endl; cout << "dist 3 = "; dist 3. showdist(); cout << endl; getch(); } 16. 02. 2018 28

Пример перегрузки бинарной операции + (с использованием операторной функции-друга) #include <iostream> #include <conio. h> Пример перегрузки бинарной операции + (с использованием операторной функции-друга) #include #include using namespace std; class Distance // Класс английских мер длины { private: int feet; // футы float inches; // дюймы public: Distance(): feet(0), inches(0. 0){} Distance(int ft, float in): feet(ft), inches(in){} void getdist(); void showdist(); //сложение двух длин friend Distance operator+(Distance d 1, Distanmce d 2); }; 16. 02. 2018 29

> feet; cout <<" src="https://present5.com/presentation/34257183_156078422/image-30.jpg" alt="void Distance: : getdist() {cout << "nvvod feet: "; cin >> feet; cout <<" /> void Distance: : getdist() {cout << "nvvod feet: "; cin >> feet; cout << "vvod inches: "; cin >> inches; } void Distance: : showdist() { cout << feet << "'-" << inches << '"'; } Distance operator+(Distance d 1, Distance d 2) {int f = d 1. feet +d 2. feet; // складываем футы float i = d 1. inches +d 2. inches; // складываем // дюймы if (i >= 12. 0) { i-=12. 0; // уменьшаем дюймы на 12 f++; } // и увеличиваем футы на 1 return Distance(f, i); //создаем и возвращаем // временный объект } 16. 02. 2018 30

int main () { Distance dist 1, dist 3; dist 1. getdist(); Distance dist int main () { Distance dist 1, dist 3; dist 1. getdist(); Distance dist 2(11, 6. 25); dist 3 = dist 1+ dist 2; cout << "ndist 1 = "; dist 1. showdist(); cout << endl; cout << "dist 2 = "; dist 2. showdist(); cout << endl; cout << "dist 3 = "; dist 3. showdist(); cout << endl; getch(); } 16. 02. 2018 31

Пример перегрузки унарной операции ++ #include <iostream> class Point { int x, y; //2 Пример перегрузки унарной операции ++ #include class Point { int x, y; //2 -мерные координаты public: Point() { x = у = 0; } Point(int i, int j) {x = i; у = j; } Point operator++(); //префиксная форма "++" Point operator++ (int); //постфиксная форма "++" void show () ; }; // перегрузка префиксной версии операции " ++ " Point : : operator++() { x++; y++; // увеличиваем координаты х, у return *this; } // возвращаем измененное // значение объекта 16. 02. 2018 32

// перегрузка постфиксной версии операции // перегрузка постфиксной версии операции " ++ " Point : : operator++(int) { temp = *this; // сохраняем исходное значение x++; y++; // увеличиваем координаты х, у return temp; // возвращаем исходное // значение объекта } int main () { Point a(l, 2), b; b = ++a; // Объект b получает значение // объекта а после ++ b = a++; // Объект b получает значение // объекта а до ++ . . . } 16. 02. 2018 33

Статические поля и методы класса Ø Определение и инициализация статического поля: тип имя_класса : Статические поля и методы класса Ø Определение и инициализация статического поля: тип имя_класса : : имя_поля инициализатор; Ø Пример, int complex: : count = 0; Ø Обращение к статическому полю через имя объекта: имя_объекта. имя_статического_поля Ø Обращение к статическому полю через имя класса: имя_класса : : имя_статического_поля Ø Вызов статического метода класса: имя_класса : : имя_статического_метода 34

Ø Статические поля и методы объявляются в классе с ключевым словом static. Ø Значение Ø Статические поля и методы объявляются в классе с ключевым словом static. Ø Значение статического поля существует в единственном экземпляре для всех объектов. Доступ к значению статического поля возможен только после его определения и инициализации. Ø Определение статического поля с инициализацией должно быть размещено в глобальной области после определения класса. Только при определении и инициализации статическое поле класса получает память и становится доступным. Ø Обращаться к статическому полю класса можно обычным образом через имя объекта. Но к статическим компонентам можно обращаться и тогда, когда объект класса еще не существует. Доступ к статическим компонентам возможен не только через имя объекта, но и через имя класса. Обращаться к статическим полям через имя класса возможно только в том случае, если они объявлены в классе в секции public. Ø Для обращения к private статическому полю извне можно с помощью статических методов. Эти методы можно вызвать через имя класса. 35

 Пример: #include <iostream. h> class TPoint { double x, y; static int N; Пример: #include class TPoint { double x, y; static int N; //количество точек public: TPoint(double x 1=0. 0, double y 1=0. 0) { N++; x = x 1; y = y 1; } static int& count(){return N; } }; int TPoint: : N=0; //инициализация статического поля void main(void) { TPoint A(1. 0, 2. 0); TPoint B(4. 0, 5. 0); TPoint C(7. 0, 8. 0); cout << "n. Определены" << TPoint: : count()<<"точки"; } 36

1. 2. 3. 4. Контрольные вопросы Как организовать передачу объектов в функции и возвращение 1. 2. 3. 4. Контрольные вопросы Как организовать передачу объектов в функции и возвращение объекта из функции? Друзья класса – понятие, назначение и основные свойства. Как осуществляется перегрузка операций в С++. В чем состоят различия между перегрузкой операций с использованием дружественных функций и без них? Какую роль играет указатель this при перегрузке операций? Статические поля и методы класса: назначение, синтаксис описания и примеры использования 37