12 лаба ИТ ЛЭТИ. Перегрузка операторов для пользовательских типов
Скачать 77.63 Kb.
|
МИНОБРНАУКИ РОССИИ САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ «ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА) Кафедра телевидения и видеотехники ОТЧЕТ по лабораторной работе №12 по дисциплине «Информатика» Тема: ПЕРЕГРУЗКА ОПЕРАТОРОВ ДЛЯ ПОЛЬЗОВАТЕЛЬСКИХ ТИПОВ
Санкт-Петербург 2022 Цель работы: Приобретение практических навыков в составлении программ со структурами и классами. 1 ПРАВИЛА ПЕРЕГРУЗКИ ОПЕРАТОРОВ Механизм перегрузки операций позволяет обеспечить более традиционную и удобную запись действий над объектами. Для перегрузки встроенных операторов используется ключевое слово operator. Синтаксически перегрузка операций осуществляется следующим образом: тип operator @ (список_параметров-операндов) { // тело функции } где @ — знак перегружаемой операции (-, +, *, /, >, < и т.д.), тип — тип возвращаемого значения. Тип возвращаемого значения должен быть отличным от void, если необходимо использовать перегруженную операцию внутри другого выражения. Правила перегрузки операций - язык C++ не допускает определения для операций нового лексического символа, кроме уже определенных в языке. Например, нельзя определить в качестве знака операции @; - не допускается перегрузка операций для встроенных типов данных. Нельзя, например, переопределить операцию сложения целых чисел: intoperator +(inti, intj); - нельзя переопределить приоритет операции. - перегружать можно только операции, для которых хотя бы один аргумент представляет тип данных, определенный пользователем. Функция-операция должна быть определена либо как функция-член класса, либо как внешняя функция, но дружественная классу. 2 ОПЕРАТОРЫ ВЫВОДА В ПОТОК Определим оператор вывода в поток, который принимает в качестве первого аргумента поток, в качестве второго константную ссылку на экземпляр объекта, а возвращает ссылку на поток. Пример 12.2 Оператор вывода в поток ostream& operator<<(ostream& stream, const Time& t) { stream << setfill('0'); //добавляем «0» stream << setw(2) << t.hour << ':' << setw(2) << t.min<< ':' << setw(2) << t.sec; returnstream; } Теперь доступна следующая запись: int main(){ Time t1 = { 2, 50, 30 }; cout << t1 << endl; return 0; } Результат вывода в консоль: 02:50:30. “0” перед “2” появился за счет setfill('0'). 3 ОПЕРАТОР ВВОДА В ПОТОК Аналогичным образом определяется оператор ввода из потока. Пример 12.3 Оператор ввода в поток istream& operator>>(istream& stream, Time& t) { stream >> t.hour; stream.ignore(1); //игнорируем 1 символ stream >> t.min; stream.ignore(1); stream >> t.sec; return stream; } 4 ПЕРЕГРУЗКА АРИФМЕТИЧЕСКИХ ОПЕРАЦИЙ Реализуем возможность складывать время естественным образом Пример 12.4 Timet1 = {2, 50, 30}; Timet2 = {0, 35, 15}; cout << t1 + t2 << endl; /* ошибка компиляции, т.к. не определен оператор +*/ Определим оператор +, который принимает в качестве первого и второго аргументов константную ссылку на экземпляр объекта. Пример 12.5 Time operator+(const Time& l, const Time& r) { return Time(l.hour + r.hour, l.min + r.min, l.sec + r.sec); } Результат работы кода: 02:85:45. 5 ПЕРЕГРУЗКА ОПЕРАТОРОВ СРАВНЕНИЯ Реализуем возможность сравнивать два значения времени. Пример 12.6 Time t1 = {2, 50, 30}; Time t2 = {0, 35, 15}; bool operator<(const Time& l, const Time& r) { return l.sec*l.min*l.hour < r.sec*r.min*r.hour; } Упражнение 1. Класс Drob #include using namespace std; class Drob { private: int chisl; int znam; public: Drob(const int& a = 0, const int& b = 1) : chisl{ a }, znam { b } {} friend std::istream& operator>> (std::istream& in, Drob& drob); friend const Drob& operator+(const Drob& f, const Drob& s); friend const Drob& operator-(const Drob& f, const Drob& s); friend const Drob& operator*(const Drob& f, const Drob& s); friend const Drob& operator/(const Drob& f, const Drob& s); friend bool operator<(const Drob& f, const Drob& s); friend bool operator<=(const Drob& f, const Drob& s); friend bool operator==(const Drob& f, const Drob& s); friend bool operator>=(const Drob& f, const Drob& s); friend bool operator>(const Drob& f, const Drob& s); void set_chisl(const int& a ) { chisl = a; } void set_znam(const int& b) { if (b != 0) { znam = b; } } int get_chisl() { return chisl; } int get_znam() { return znam; } int NOD( int a, int b) { if (a < b) { swap(a, b); } while (a % b != 0) { a = a % b; swap(a, b); } return b; } void print() { if (znam > 0) { cout << chisl / NOD(abs(chisl), abs(znam)) << "/" << znam / NOD(abs(chisl), abs(znam)) << endl; } else { cout << chisl/ NOD(abs(chisl), abs(znam))*-1 << "/"< } }; istream& operator>>(istream& stream,Drob& d) { stream >> d.chisl; d.set_chisl(d.chisl); stream.ignore(1); stream >> d.znam; d.set_znam(d.znam); return stream; } const Drob& operator+(const Drob& f, const Drob& s) { return Drob(f.chisl * s.znam + s.chisl * f.znam, f.znam * s.znam); } const Drob& operator-(const Drob& f, const Drob& s) { return Drob(f.chisl * s.znam - s.chisl * f.znam, f.znam * s.znam); } const Drob& operator*(const Drob& f, const Drob& s) { return Drob(f.chisl * s.chisl , f.znam * s.znam); } const Drob& operator/(const Drob& f, const Drob& s) { return Drob(f.chisl * s.znam, f.znam * s.chisl); } bool operator<(const Drob& f, const Drob& s) { return f.chisl * s.znam < s.chisl* f.znam; } bool operator<=(const Drob& f, const Drob& s) { return f.chisl * s.znam <= s.chisl* f.znam; } bool operator>(const Drob& f, const Drob& s) { return f.chisl * s.znam > s.chisl* f.znam; } bool operator>=(const Drob& f, const Drob& s) { return f.chisl * s.znam >= s.chisl* f.znam; } bool operator==(const Drob& f, const Drob& s) { return f.chisl * s.znam == s.chisl * f.znam; } void func(Drob d1, const string& op, Drob d2) { Drob d3; if (op == "+") { d3 = (d1 + d2); d3.print(); } else if (op == "-") { d3 = (d1 - d2); d3.print(); } else if (op == "*") { d3 = (d1 * d2); d3.print();} else if (op == "/") { d3 = (d1 / d2); d3.print(); } else if (op == "<") { if (d1 < d2){cout << "Da" << endl; } else { cout << "No" << endl; } } else if (op == ">") { if (d1 > d2) { cout << "Da" << endl; } else { cout << "No" << endl; } } else if (op == "==") { if (d1 == d2) { cout << "Da" << endl; } else { cout << "No" << endl; } } else if (op == "<=") { if (d1 <= d2) { cout << "Da" << endl; } else { cout << "No" << endl; } } else if (op == ">=") { if (d1 >= d2) { cout << "Da" << endl; } else { cout << "No"<< endl; } } } int main() { Drob d1,d2,d3; string op; for (int i = 0; i < 6; i++) { cin >> d1; cin.ignore(1); cin >> op; cin.ignore(1); cin >> d2; func(d1, op, d2); cout << "----------------------------------------------"; } } Вывод: была проведена лабораторная работа в ходе которой были изучены способы перегрузки операторов для пользовательских типов. Созданы перегрузки различных операторов(сравнения, арифметических, ввода и вывода). |