Перейти к основному содержанию
EDU-MMCS
  • В начало
  • Дополнительно
Вы используете гостевой доступ
Вход
В начало
  1. Prog_3
  2. Лабораторная работа 7 "Перегрузка операций"

Лабораторная работа 7 "Перегрузка операций"

Требуемые условия завершения
Открыто с: пятница, 7 ноября 2025, 00:00
Срок сдачи: пятница, 14 ноября 2025, 00:00

1. Что такое перегрузка операций?

Перегрузка операций - это возможность в C++ определять собственное поведение для стандартных операторов (+, -, *, /, =, == и др.) при работе с пользовательскими типами данных (классами).

Пример без перегрузки:

cpp
Complex c1, c2, c3;
c3 = c1.add(c2);  // Неудобно!

Пример с перегрузкой:

cpp
Complex c1, c2, c3;
c3 = c1 + c2;  // Естественно и понятно!

2. Два способа перегрузки

Способ 1: Методы класса

Оператор становится методом класса. Левый операнд - это текущий объект (this).

cpp
class Complex {
public:
    // Метод класса - левый операнд this, правый other
    Complex operator+(const Complex& other) const {
        return Complex(real + other.real, imag + other.imag);
    }
};

Когда использовать:

  • Когда левый операнд ОБЯЗАТЕЛЬНО объект вашего класса

  • Для операций, где текущий объект - главный

Способ 2: Дружественные функции

Отдельные функции, объявленные как friend, имеют доступ к приватным полям.

cpp
class Complex {
private:
    double real, imag;
public:
    // Объявление дружественной функции
    friend Complex operator+(const Complex& c1, const Complex& c2);
};

// Реализация дружественной функции
Complex operator+(const Complex& c1, const Complex& c2) {
    return Complex(c1.real + c2.real, c1.imag + c2.imag);
}

Когда использовать:

  • Когда левый операнд НЕ объект вашего класса

  • Для симметричных операций (5 + obj и obj + 5)

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

3. Синтаксис перегрузки

Для методов класса:

cpp
ReturnType operator#(Parameters) const;
// # - оператор (+, -, *, / и т.д.)

Для дружественных функций:

cpp
friend ReturnType operator#(Parameter1, Parameter2);

4. Возвращаемые значения

  • Арифметические операторы (+, -, *, /) → возвращают новый объект

  • Операторы присваивания (=, +=, -=) → возвращают ссылку на текущий объект

  • Операторы сравнения (==, !=, <, >) → возвращают bool

5. Особые случаи

Унарные операторы:

cpp
// Префиксный ++ (метод класса)
Complex& operator++() {
    real++; imag++;
    return *this;
}

Операторы ввода/вывода:

cpp
// Только через дружественные функции!
friend ostream& operator<<(ostream& os, const Complex& c) {
    os << c.real << " + " << c.imag << "i";
    return os;
}

6. Правила и ограничения

МОЖНО:

  • Перегружать большинство операторов

  • Использовать оба способа перегрузки

  • Возвращать любые типы

НЕЛЬЗЯ:

  • Создавать новые операторы

  • Изменять приоритет операторов

  • Изменять количество операндов

  • Перегружать операторы . (точка), .*, ::, ?:


Пример

cpp
#include <iostream>
using namespace std;

class Complex {
private:
    double real;
    double imag;

public:
    // Конструктор
    Complex(double r = 0, double i = 0) : real(r), imag(i) {}
    
    // Геттеры
    double getReal() const { return real; }
    double getImag() const { return imag; }
    
    // Вывод числа
    void show() const {
        cout << real;
        if (imag >= 0)
            cout << " + " << imag << "i";
        else
            cout << " - " << -imag << "i";
    }
    
    // === ПЕРЕГРУЗКА ЧЕРЕЗ МЕТОДЫ КЛАССА ===
    
    // Сложение комплексных чисел
    Complex operator+(const Complex& other) const {
        return Complex(real + other.real, imag + other.imag);
    }
    
    // Вычитание комплексных чисел
    Complex operator-(const Complex& other) const {
        return Complex(real - other.real, imag - other.imag);
    }
    
    // Умножение комплексных чисел
    Complex operator*(const Complex& other) const {
        // (a+bi)*(c+di) = (ac-bd) + (ad+bc)i
        double r = real * other.real - imag * other.imag;
        double i = real * other.imag + imag * other.real;
        return Complex(r, i);
    }
    
    // === ДРУЖЕСТВЕННЫЕ ФУНКЦИИ ===
    
    // Сложение с целым числом
    friend Complex operator+(const Complex& c, double num) {
        return Complex(c.real + num, c.imag);
    }
    
    // Вычитание целого числа
    friend Complex operator-(const Complex& c, double num) {
        return Complex(c.real - num, c.imag);
    }
    
    // Деление на целое число
    friend Complex operator/(const Complex& c, double num) {
        if (num == 0) {
            cout << "Ошибка: деление на 0!" << endl;
            return Complex();
        }
        return Complex(c.real / num, c.imag / num);
    }
};

// Демонстрация работы
int main() {
    Complex a(3, 4);  // 3 + 4i
    Complex b(1, 2);  // 1 + 2i
    
    cout << "a = "; a.show(); cout << endl;
    cout << "b = "; b.show(); cout << endl << endl;
    
    cout << "МЕТОДЫ КЛАССА:" << endl;
    Complex c = a + b;  cout << "a + b = "; c.show(); cout << endl;
    c = a - b;         cout << "a - b = "; c.show(); cout << endl;
    c = a * b;         cout << "a * b = "; c.show(); cout << endl;
    
    cout << "\nДРУЖЕСТВЕННЫЕ ФУНКЦИИ:" << endl;
    c = a + 5;  cout << "a + 5 = "; c.show(); cout << endl;
    c = a - 2;  cout << "a - 2 = "; c.show(); cout << endl;
    c = a / 2;  cout << "a / 2 = "; c.show(); cout << endl;
    
    return 0;
}

ЗАДАНИЯ: Класс Vector2D

Задание 1: Базовые операции

Создайте класс Vector2D для работы с двумерными векторами.

Требования:

Поля класса:

  • x - координата X (double)

  • y - координата Y (double)

Конструктор:

  • Vector2D(double x_val = 0, double y_val = 0)

Методы класса (перегрузка через МЕТОДЫ):

  1. Vector2D operator+(const Vector2D& other) const - сложение векторов

  2. Vector2D operator-(const Vector2D& other) const - вычитание векторов

  3. double operator*(const Vector2D& other) const - скалярное произведение

Дружественные функции:

  1. friend Vector2D operator+(const Vector2D& v, double num) - с числом

  2. friend Vector2D operator-(const Vector2D& v, double num) - с числом

  3. friend Vector2D operator/(const Vector2D& v, double num) - деление

Вспомогательные методы:

  • void show() const - вывод вектора

Пример использования:

cpp
Vector2D v1(2, 3), v2(1, 4);
Vector2D v3 = v1 + v2;    // (3, 7)
double dot = v1 * v2;     // 14 (скалярное произведение)
Vector2D v4 = v1 / 2;     // (1, 1.5)

Задание 2: Дополнительные операции

Добавьте к классу Vector2D следующие операции:

Методы класса:

  1. bool operator==(const Vector2D& other) const - сравнение на равенство

  2. Vector2D operator-() const - унарный минус

Дружественные функции:

  1. friend ostream& operator<<(ostream& os, const Vector2D& v) - вывод в поток

  2. friend Vector2D operator*(const Vector2D& v, double num) - умножение на число

  3. friend Vector2D operator*(double num, const Vector2D& v) - число на вектор

Пример использования:

cpp
Vector2D v1(2, 3), v2(2, 3);
if (v1 == v2) cout << "Векторы равны" << endl;
cout << v1;               // Вывод: (2, 3)
Vector2D v3 = -v1;        // (-2, -3)
Vector2D v4 = v1 * 2;     // (4, 6)
Vector2D v5 = 3 * v1;     // (6, 9)

Задание 3: Расширенные возможности

Добавьте продвинутые операции:

Методы класса:

  1. Vector2D& operator+=(const Vector2D& other) - сложение с присваиванием

  2. Vector2D& operator-=(const Vector2D& other) - вычитание с присваиванием

  3. double length() const - длина вектора

Дружественные функции:

  1. friend double dotProduct(const Vector2D& v1, const Vector2D& v2) - скалярное произведение

  2. friend bool arePerpendicular(const Vector2D& v1, const Vector2D& v2) - проверка перпендикулярности

Пример использования:
cpp
Vector2D v1(3, 4), v2(1, 0);
v1 += v2;                 // v1 становится (4, 4)
cout << "Длина: " << v1.length(); // 5.65685
if (arePerpendicular(v1, v2)) {
    cout << "Векторы перпендикулярны";
}

Подсказки для реализации:

Формулы для векторов:

cpp
// Сложение: (x1, y1) + (x2, y2) = (x1+x2, y1+y2)
// Вычитание: (x1, y1) - (x2, y2) = (x1-x2, y1-y2)
// Скалярное произведение: x1*x2 + y1*y2 (возвращает double!)
// Длина вектора: sqrt(x*x + y*y)
// Унарный минус: (-x, -y)

Важные моменты:

  1. Проверяйте деление на ноль

  2. Скалярное произведение возвращает double, а не Vector2D

  3. Для operator<< возвращайте ссылку на ostream

  4. Унарный минус создает новый объект

Структура класса:

cpp
class Vector2D {
private:
    double x, y;
public:
    // Конструктор
    Vector2D(double x_val = 0, double y_val = 0) : x(x_val), y(y_val) {}
    
    // Ваш код здесь...
    
    // Вспомогательный метод
    void show() const {
        cout << "(" << x << ", " << y << ")";
    }
};



Вы используете гостевой доступ (Вход)
Сводка хранения данных
Скачать мобильное приложение Яндекс.Метрика
На платформе Moodle