Міністерство освіти і науки, молоді та спорту України
Національний університет «Львівська політехніка»
/
Звіт про виконання лабораторної роботи№ 5
Варіант №6
Перевантаження операторів
Мета роботи: познайомитися із перевантаженням операторів.
Короткі теоретичні відомості
Перевантаження операторів
Кожному оператору мова С++ ставить у відповідність ім'я функції, що складається з ключового слова operator, власне оператору та аргументів відповідних типів:
тип operator [символ оператору] (списокПараметрів)
{
//тіло метода
}
Щоб використовувати операцію над об'єктами класів, ця операція повинна бути перевантажена, але є два виключення. Операція присвоювання (=) може бути використана з кожним класом без явного перевантаження. За замовчуванням операція присвоювання зводиться до побітового копіювання даних-елементів класу. Проте таке побітове копіювання небезпечне для класів з елементами, що вказують на динамічно виділені області пам'яті; для таких класів слід явно перевантажувати операцію присвоювання. Операція адресації (&) також може бути використана з об'єктами будь-яких класів без перевантаження; вона просто повертає адресу об'єкта в пам'яті. Але операцію адресації можна також і перевантажувати.
Перевантаження операцій підпорядковується наступним правилам:
При перевантаженні зберігаються кількість аргументів, пріоритети операцій та правила асоціації, що використовуються у стандартних типах даних;
Для стандартних типів даних операції не підлягають перевизначенню;
Перевантажена функція-оператор не може мати параметрів по замовчуванню, не успадковується та не може бути визначеною як static;
Функція-оператор може бути визначена трьома способами – метод класу, дружня функція або звичайна функція. В останніх двох випадках вона повинна приймати хоча б один аргумент, що має тип класу, покажчика або посилання на клас.
При перевантаженні операцій ( ), [], -> або = функція перевантаження операції повинна бути оголошена як елемент класу. Для інших операцій функції перевантаження операцій можуть не бути функціями-елементами.
Коли функція-операція реалізована як функція-елемент, крайній лівий (або єдиний) операнд повинен бути об'єктом того класу (або посиланням на об'єкт того класу), елементом якого є функція. Якщо лівий операнд повинен бути об'єктом іншого класу або убудованого типу, така функція-операція не може бути реалізована як функція-елемент. Функція-операція, реалізована не як функція-елемент, повинна бути другом, якщо ця функція повинна мати прямий доступ до закритих або захищених елементів цього класу. Щоб оголосити функцію як друга (frіend) класу, перед її прототипом в описі класу ставиться ключове слово frіend. Дружні функції класу визначаються поза областю дії класу, але мають право доступу до закритих елементів класу.
Перевантажена операція << повинна мати лівий операнд типу ostream & (такий, як cout), так що вона не може бути функцією-елементом. Аналогічно, перевантажена операція >> повинна мати лівий операнд типу іstream & (такий, як cіn), так що вона теж не може бути функцією-елементом. До того ж кожна з цих перевантажених функцій-операцій може забажати доступу до закритих елементів-даних об'єкта класу, так що ці перевантажені функції-операції роблять функціями-друзями класу.
Будь-яку бінарну операцію можна перевантажувати як нестатичну функцію-елемент з одним аргументом, або як функцію, що не є елементом, із двома аргументами (один з цих аргументів повинен бути або об'єктом класу, або посиланням на об'єкт класу).
Унарну операцію класу можна перевантажувати як функцію-елемент без аргументів, або як функцію, що не є елементом, з одним аргументом; цей аргумент повинен бути або об'єктом класу, або посиланням на об'єкт класу. Функції-елементи, що реалізують перевантажені операції, повинні бути нестатичними, щоб вони могли мати доступ до даних класу. Нагадаємо, що статичні функції-елементи можуть мати доступ тільки до статичних даних-елементів класу.
При перевантаженні унарних операцій переважно створюють функції-операції, що є елементами класу, замість дружніх функцій, що не є елементами. Дружніх функцій краще уникати доти, поки вони не стануть абсолютно необхідними. Використання друзів порушує інкапсуляцію класу.
Щоб перевантажити операцію інкремента та декремента для одержання можливості використання і префіксної, і постфіксної форм, кожна з цих двох перевантажених функцій-операцій повинна мати різну сигнатуру, щоб компілятор мав можливість визначити, яка версія мається на увазі в кожному конкретному випадку. Префіксний варіант перевантажується як будь-яка інша префіксна унарна операція. Для постфіксної форми вводиться додатковий параметр цілого типу у список аргументів, щоб зробити функцію для постфіксного варіанту відмінною від функції для префіксної форми.
Зауваження щодо перевантаження операцій:
Існують обмеження на перевантаження: не підлягають цій процедурі селектор елемента структури (.), оператор доступу до елементу за покажчиком (*), операція дозволу видимості (::), символи препроцесору (#, ##) та sizeof(). Неможливим є введення власних операторів.
Компілятор С++ не розуміє семантики перевантаженого оператору, а отже, не нав'язує жодних математичних концепцій. Можна перевантажити, скажімо, оператор інкременту в якості зменшення аргументу, проте навряд чи в цьому є сенс.
Не існує виведення складних операторів з простих: якщо ви перевантажили оператори operator+ та operator=, це зовсім не означає, що С++ обчислить вираз a += b, оскільки ви не перевантажили operator +=.
Перевантаження бінарних операторів не тотожньо відносно перестановки аргументів місцями, тим більше, якщо вони різного типу.
Завдання
Описати клас, що реалізовує вказаний нижче тип даних. Клас повинен містити множину конструкторів для створення об'єктів певного типу (конструктор по замочуванню та з параметрами, конструктор копії) та подані у таблиці операції над об'єктами класу (плюс обов'язково операцію присвоювання) з використанням механізму перевантаження операцій.
Написати програму, яка демонструє роботу з об'єктами цього класу. Організувати виведення та введення даних за допомогою класів-потоків сin та cout.
6
Клас Set (множини)
Операції: об’єднання множин(+ =), перетин множин (- =).
Код програми
файл main.cpp
#include "set.h";
int main() {
int n1,n2,i;
cout << "Kilkist elementiv v mnozhini A: ";
cin >> n1;
double *masiv1 = new double [n1]; //Initsializuemo masiv pid mnozuny
cout << "Vedit elementu mnozhini A: \n";
for (i = 0;i<n1;i++) cin >> masiv1[i];
cout << "____________________________________________\nKilkist elementiv v mnozhini B: ";
cin >> n2;
double *masiv2 = new double [n2]; //Initsializuemo masiv pid mnozuny
cout << "Vedit elementu mnozhini B: \n";
for (i = 0;i<n2;i++) cin >> masiv2[i];
Set A(masiv1,n1); //Stvoruemo mnozhuny A
cout << "\nA:" << A << "\n";
Set B(masiv2,n2); //Stvoruemo mnozhuny B
cout << "\nB:" << B << "\n";
Set C;
C = A-= B;
cout << "\nPeretun:" << C << "\n";
C = A+= B;
cout << "Obednanna:" << C << "\n";
return 0;
}
файл set.cpp
#include "set.h";
//Îïèñ êîíñòðóêòîðà, ÿêèé ³í³ö³àë³çóº ìíîæèíó
Set::Set(double arr[], int n) {
int i;
for (i=0;i<n;i++) mn[i] = arr[i];
N = n;
}
Set::Set() {
}
Set Set::operator +=(Set&arr) {
Set C = *this; //Object yaki bude povertatis
int i,j;
//Vukluchemo z mn B vsi povtoruvani elementu
for (i=0;i<C.N;i++)
for (0;j<arr.N;j++) {
if ((C.mn[i]==arr.mn[j]) & (arr.mn[i]!=-999)) {
arr.mn[j] = -999;
}
}
int from = C.N;
int max;
if (arr.N>C.N) max = arr.N; else max = C.N;
//Vukonuemo dodavanna
for(i=0;i<max+1;i++) {
if (arr.mn[i]!=-999) {
C.mn[from]=arr.mn[i];
from++;
}
}
C.N=from-1;
return C;
}
Set Set::operator -=(Set&arr) {
Set C = *this;
Set K;
//vUKLUTSHEMO ODNAKOVI ELEMENTU
int i,j,k=0;
for(i=0;i<C.N-1;i++)
for (j=i+1;j<C.N;j++) {
if (C.mn[i]==C.mn[j]) C.mn[j]=-999;
}
for(i=0;i<arr.N-1;i++)
for (j=i+1;j<arr.N;j++) {
if (arr.mn[i]==arr.mn[j]) arr.mn[j]=-999;
}
for(i=0;i<C.N;i++)
for (j=0;j<arr.N;j++)
if ((C.mn[i]==arr.mn[j]) & (C.mn[i]!=-999)) {
K.mn[k]=C.mn[i];
k++;
}
K.N = k;
return K;
}
ostream& operator<< (ostream &output,Set &arr) {
for(int i = 0; i < arr.N; i++)
{
output << arr.mn[i] << " ";
}
output << endl;
return output;
}
файл set.h
#include <iostream>
using namespace std;
class Set {
friend ostream& operator<< (ostream& output, Set &arr);
public:
int N; // kilkist elemetiv v mnozhini
double mn[100];
Set(); //Constructor po zamovshuvanu
Set(double arr[], int n);
Set operator+=(Set &arr); //pROTOTUP OPERATORY OBEDNANNA
Set operator-=(Set &arr);
ostream& operator<< (ostream &output);
};
/