Міністерство освіти і науки
Національний університет “Львівська політехніка”
Кафедра ЕОМ
/
Звіт
з лабораторної роботи № 7
з дисципліни: “Об’єктно-орієнтоване програмування”
на тему: “Перевантаження операторів”
Мета лабораторної роботи
Познайомитися із перевантаженням операторів в мові C++.
Теоретичні відомості
Перевантаження операторів
Ключове слово operator використовується для того, аби визначити нову, перевантажену дію конкретного оператора мови.
Кожному оператору мова С++ ставить у відповідність ім'я функції, що складається з ключового слова operator, власне оператору та аргументів відповідних типів:
тип operator<символ оператору> (список параметрів)
{
//тіло метода
}
Щоб використовувати операцію над об'єктами класів, ця операція повинна бути перевантажена, але є два виключення. Операція присвоювання (=) може бути використана з кожним класом без явного перевантаження. За замовчуванням операція присвоювання зводиться до побітового копіювання даних-елементів класу. Проте таке побітове копіювання небезпечне для класів з елементами, що вказують на динамічно виділені області пам'яті; для таких класів слід явно перевантажувати операцію присвоювання. Операція адресації (&) також може бути використана з об'єктами будь-яких класів без перевантаження; вона просто повертає адресу об'єкта в пам'яті. Але операцію адресації можна також і перевантажувати.
Перевантаження операцій підпорядковується наступним правилам:
При перевантаженні зберігаються кількість аргументів, пріоритети операцій та правила асоціації, що використовуються у стандартних типах даних;
Для стандартних типів даних операції не підлягають перевизначенню;
Перевантажена функція-оператор не може мати параметрів по замовчуванню, не успадковується та не може бути визначеною як static.
Функція-оператор може бути визначена трьома способами – метод класу, дружня функція або звичайна функція. В останніх двох випадках вона повинна приймати хоча б один аргумент, що має тип класу, покажчика або посилання на клас.
При перевантаженні операцій ( ), [], -> або = функція перевантаження операції повинна бути оголошена як елемент класу. Для інших операцій функції перевантаження операцій можуть не бути функціями-елементами.
Коли функція-операція реалізована як функція-елемент, крайній лівий (або єдиний) операнд повинен бути об'єктом того класу (або посиланням на об'єкт того класу), елементом якого є функція. Якщо лівий операнд повинен бути об'єктом іншого класу або убудованого типу, така функція-операція не може бути реалізована як функція-елемент. Функція-операція, реалізована не як функція-елемент, повинна бути другом, якщо ця функція повинна мати прямий доступ до закритих або захищених елементів цього класу. Щоб оголосити функцію як друга (frіend) класу, перед її прототипом в описі класу ставиться ключове слово frіend. Дружні функції класу визначаються поза областю дії класу, але мають право доступу до закритих елементів класу.
Перевантажена операція << повинна мати лівий операнд типу ostream & (такий, як cout), так що вона не може бути функцією-елементом. Аналогічно, перевантажена операція >> повинна мати лівий операнд типу іstream & (такий, як cіn), так що вона теж не може бути функцією-елементом. До того ж кожна з цих перевантажених функцій-операцій може забажати доступу до закритих елементів-даних об'єкта класу, так що ці перевантажені функції-операції роблять функціями-друзями класу.
Будь-яку бінарну операцію можна перевантажувати як нестатичну функцію-елемент з одним аргументом, або як функцію, що не є елементом, із двома аргументами (один з цих аргументів повинен бути або об'єктом класу, або посиланням на об'єкт класу).
Унарну операцію класу можна перевантажувати як функцію-елемент без аргументів, або як функцію, що не є елементом, з одним аргументом; цей аргумент повинен бути або об'єктом класу, або посиланням на об'єкт класу. Функції-елементи, що реалізують перевантажені операції, повинні бути нестатичними, щоб вони могли мати доступ до даних класу. Нагадаємо, що статичні функції-елементи можуть мати доступ тільки до статичних даних-елементів класу.
При перевантаженні унарних операцій переважно створюють функції-операції, що є елементами класу, замість дружніх функцій, що не є елементами. Дружніх функцій краще уникати доти, поки вони не стануть абсолютно необхідними. Використання друзів порушує інкапсуляцію класу.
Щоб перевантажити операцію інкремента та декремента для одержання можливості використання і префіксної, і постфіксної форм, кожна з цих двох перевантажених функцій-операцій повинна мати різну сигнатуру, щоб компілятор мав можливість визначити, яка версія мається на увазі в кожному конкретному випадку. Префіксний варіант перевантажується як будь-яка інша префіксна унарна операція. Для постфіксної форми вводиться додатковий параметр цілого типу у список аргументів, щоб зробити функцію для постфіксного варіанту відмінною від функції для префіксної форми.
Зауваження щодо перевантаження операцій:
Існують обмеження на перевантаження: не підлягають цій процедурі селектор елемента структури (.), оператор доступу до елементу за покажчиком (*), операція дозволу видимості (::), символи препроцесору (#, ##) та sizeof(). Неможливим є введення власних операторів.
Компілятор С++ не розуміє семантики перевантаженого оператору, а отже, не нав'язує жодних математичних концепцій. Можна перевантажити, скажімо, оператор інкременту в якості зменшення аргументу, проте навряд чи в цьому є сенс.
Не існує виведення складних операторів з простих: якщо ви перевантажили оператори operator+ та operator=, це зовсім не означає, що С++ обчислить вираз a += b, оскільки ви не перевантажили operator +=.
Перевантаження бінарних операторів не тотожньо відносно перестановки аргументів місцями, тим більше, якщо вони різного типу.
Індивідуальне завдання
Описати клас, що реалізовує вказаний нижче тип даних. Клас повинен містити множину конструкторів для створення об'єктів певного типу (конструктор по замочуванню та з параметрами, конструктор копії) та подані у таблиці операції над об'єктами класу (плюс обов'язково операцію присвоювання) з використанням механізму перевантаження операцій.
Написати програму, яка демонструє роботу з об'єктами цього класу. Організувати виведення та введення даних за допомогою класів-потоків сin та cout.
4. Клас HugeInt (цілі числа).
Операції: – =, порівняння (<, >).
Код програми
main.cpp
#include <iostream>
#include <conio.h>
#include "HugeInt.h"
using namespace std;
int main()
{
setlocale(LC_ALL, "Ukrainian");
int num1, num2, old, reduce;
cout << "Введiть числа a i b:" << endl << "a = ";
cin >> num1;
cout << "b = ";
cin >> num2;
HugeInt a(num1), b(num2);
for (;;)
{
system("cls");
cout << "a = " << a.GetValue() << "; b = " << b.GetValue() << endl
<< "[1] Ввести числа спочатку" << endl << "[2] Зменшити число a" << endl
<< "[3] Зменшити число b" << endl << "[4] Перевiрити a < b" << endl
<< "[5] Перевiрити a > b" << endl << "[0] Вихiд" << endl;
switch (_getch())
{
case '1':
system("cls");
cout << "Введiть числа a i b:" << endl << "a = ";
cin >> num1;
cout << "b = ";
cin >> num2;
a = num1;
b = num2;
break;
case '2':
system("cls");
cout << "Зменшити число a на ";
cin >> reduce;
old = a.GetValue();
a -= reduce;
cout << "a = " << old << " - " << reduce << " = " << a.GetValue();
_getch();
break;
case '3':
system("cls");
cout << "Зменшити число b на ";
cin >> reduce;
old = b.GetValue();
b -= reduce;
cout << "a = " << old << " - " << reduce << " = " << b.GetValue();
_getch();
break;
case '4':
system("cls");
cout << "a = " << a.GetValue() << "; b = " << b.GetValue() << endl
<< "a < b : ";
if (a < b)
cout << "true" << endl;
else
cout << "false" << endl;
_getch();
break;
case '5':
system("cls");
cout << "a = " << a.GetValue() << "; b = " << b.GetValue() << endl
<< "a > b : ";
if (a > b)
cout << "true" << endl;
else
cout << "false" << endl;
_getch();
break;
case '0':
return 0;
}
}
}
HugeInt.h
class HugeInt
{
private:
int value;
public:
HugeInt(int value);
~HugeInt();
int GetValue();
HugeInt operator=(const HugeInt &num);
HugeInt operator-=(const HugeInt &num);
bool operator<(const HugeInt &num);
bool operator>(const HugeInt &num);
};
HugeInt.cpp
#include "HugeInt.h"
HugeInt::HugeInt(int value) {
this->value = value;
}
HugeInt::~HugeInt(){}
int HugeInt::GetValue() {
return value;
}
HugeInt HugeInt::operator=(const HugeInt &num) {
return value = num.value;
}
HugeInt HugeInt::operator-=(const HugeInt &num) {
return value -= num.value;
}
bool HugeInt::operator<(const HugeInt &num) {
if (value < num.value)
return true;
else
return false;
}
bool HugeInt::operator>(const HugeInt &num) {
if (value > num.value)
return true;
else
return false;
}
Результат виконання програми
/
Висновок
Я познайомився із перевантаженням операторів в мові C++ та написав програму, яка містить клас із перевантаженням операторів.