Кратко:

  1. Методы-члены: перегрузка операторов в виде методов-членов класса.
  2. Дружественные функции: перегрузка операторов с использованием дружественных функций.
  3. Свободные функции: перегрузка операторов с использованием свободных функций.

Методы-члены

  • Перегружаемые операторы определяются как методы класса.
  • Используются для операторов, где левый операнд должен быть экземпляром класса.
class Complex {
private:
    double real, imag;
 
public:
    Complex(double r = 0, double i = 0) : real(r), imag(i) {}
 
    // Перегрузка оператора + как метода-члена
    Complex operator+(const Complex &c) const {
        return Complex(real + c.real, imag + c.imag);
    }
 
    // Перегрузка оператора == как метода-члена
    bool operator==(const Complex &c) const {
        return real == c.real && imag == c.imag;
    }
};

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

Дружественные функции: позволяют внешним функциям доступ к приватным и защищённым членам класса. Объявляются внутри класса с ключевым словом friend.

Полный пример программы с использованием дружественной функции

Вот пример программы, в которой используется дружественная функция для перегрузки оператора << для класса Complex.

#include <iostream>
 
class Complex {
private:
    double real;
    double imag;
 
public:
    // Конструктор
    Complex(double r = 0, double i = 0) : real(r), imag(i) {}
 
    // Дружественная функция для перегрузки оператора <<
    friend std::ostream& operator<<(std::ostream &out, const Complex &c);
};
 
// Определение дружественной функции для перегрузки оператора <<
std::ostream& operator<<(std::ostream &out, const Complex &c) {
    out << "(" << c.real << ", " << c.imag << ")";
    return out;
}
 
int main() {
    // Создание объектов класса Complex
    Complex c1(1.2, 3.4);
    Complex c2(5.6, 7.8);
 
    // Использование перегруженного оператора <<
    std::cout << "Complex number 1: " << c1 << std::endl;
    std::cout << "Complex number 2: " << c2 << std::endl;
 
    return 0;
}

Пояснение

  1. Класс Complex:

    • Имеет приватные члены real и imag для хранения действительной и мнимой частей комплексного числа.
    • Конструктор инициализирует члены, значения по умолчанию — 0.
  2. Дружественная функция:

    • friend std::ostream& operator<<(std::ostream &out, const Complex &c); объявляется внутри класса Complex, чтобы предоставить дружественной функции доступ к приватным членам real и imag.
  3. Определение дружественной функции:

    • std::ostream& operator<<(std::ostream &out, const Complex &c) определяет, как должно выводиться комплексное число. Функция получает объект Complex и поток вывода std::ostream, а затем выводит строку в формате (real, imag).
  4. Функция main:

    • Создаёт два объекта Complex.
    • Использует перегруженный оператор << для вывода объектов Complex.

Свободные функции

  • Используются для перегрузки операторов, когда можно обойтись без доступа к приватным членам или если требуется функциональность, независимая от конкретного класса.
class Matrix {
private:
    int data[2][2];
 
public:
    Matrix(int a = 0, int b = 0, int c = 0, int d = 0) {
        data[0][0] = a; data[0][1] = b;
        data[1][0] = c; data[1][1] = d;
    }
 
    // Метод для доступа к данным
    int get(int row, int col) const {
        return data[row][col];
    }
};
 
// Свободная функция для перегрузки оператора *
Matrix operator*(const Matrix &m1, const Matrix &m2) {
    return Matrix(
        m1.get(0, 0) * m2.get(0, 0) + m1.get(0, 1) * m2.get(1, 0),
        m1.get(0, 0) * m2.get(0, 1) + m1.get(0, 1) * m2.get(1, 1),
        m1.get(1, 0) * m2.get(0, 0) + m1.get(1, 1) * m2.get(1, 0),
        m1.get(1, 0) * m2.get(0, 1) + m1.get(1, 1) * m2.get(1, 1)
    );
}

Заключение

  • Методы-члены: удобны для операторов, где левый операнд является экземпляром класса.
  • Дружественные функции: используются для доступа к приватным членам и симметричных операций.
  • Свободные функции: хороши для независимых операций и когда доступ к приватным членам не требуется.