Перегрузка сокращенных операторов присваивания. Примеры

Перегрузка сокращенных операторов присваивания +=, -=, *=, /=, %=. Примеры

Данная тема базируется на изучении следующих тем


Содержание


1. Особенности перегрузки сокращенных операторов присваивания +=, -=, *=, /=, %=. Общая форма операторной функции

Сокращенные операторы присваивания +=, -=, *=, /=, %= есть бинарными, то есть для вычислений они требуют двух операндов.
Если операторная функция реализована в классе, то она получает один операнд и имеет следующую общую форму

class ClassName
{
    // ...

    // операторная функция, которая перегружает один из сокращенных операторов присваивания
    ClassName operator##(ClassName obj)
    {
        // ...
    }
}

где

  • ClassName – имя класса, для которого реализуется операторная функция operator##();
  • operator##() – некоторая операторная функция. Символы ## заменяются символами +=, -=, *=, /=, %=, то есть, операторная функция будет иметь соответственно следующие имена: operator+=(), operator-=(), operator*=(), operator/=(), operator%=().
  • obj – экземпляр (объект) класса ClassName.

Если операторная функция реализована как «дружественная», то она получает два операнда. В этом случае, общая форма использования операторной функции имеет вид:

class ClassName
{
    // ...

    // "дружественная" операторная функция,
    // которая перегружает один из сокращенных операторов присваивания
    friend ClassName operator##(ClassName& obj1, ClassName& obj2)
    {
        // ...
    }
}

// реализация "дружественной" к классу ClassName операторной функции
ClassName operator##(ClassName& obj1, ClassName& obj2)
{
    // ...
}

здесь obj1, obj2 – ссылка на экземпляры класса ClassName, которые передаются в «дружественную» операторную функцию operator##().

 

2. Пример, который демонстрирует перегрузку оператора += для класса Integer, который реализует целое число. Операторная функция объявляется внутри класса

Задан класс Integer, реализующий операции над целочисленным значением. В классе объявляются:

  • внутренняя переменная number целого типа, которая сохраняет значение;
  • два конструктора;
  • методы доступа к целочисленной переменной number;
  • операторная функция operator+=(), которая перегружает сокращенный оператор присваивания +=.

Реализация класса Integer

// класс Integer - реализует целое число
class Integer
{
private:
    int number;

public:
    // конструкторы класса
    Integer() { number = 0; }
    Integer(int _number) { number = _number; }

    // методы доступа
    int Get(void) { return number; }
    void Set(int _number) { number = _number; }

    // перегрузка оператора +=, операторная функция внутри класса
    Integer operator+=(Integer obj)
    {
        number = number + obj.number; // доступ по ссылке
        return *this;
    }
};

Использование экземпляра (объекта) класса Integer в другом программном коде может быть, например, следующим:

// перегрузка сокращенных операторов присваивания +=, -= и т.д.
Integer d1(10), d2(18); // экземпляры класса Integer
int t;

// вызов операторной функции operator+=()
d1+=d2; // d1.number = d1.number + d2.number

t = d1.Get(); // t = 28

По данному образцу можно перегружать другие сокращенные операторы присваивания -=, *=, /=, %=.

 

3. Пример, который демонстрирует перегрузку оператора %= для класса Integer, который реализует целое число. Операторная функция объявляется как «дружественная» к классу Integer

В классе Integer объявляется «дружественная» (friend) операторная функция operator%=(), определяющая объект класса Integer, который есть остатком от деления объектов –параметров функций.

// класс Integer, реализующий целое число
class Integer
{
private:
    int number;

public:
    // конструкторы класса
    Integer() { number = 0; }
    Integer(int _number) { number = _number; }

    // методы доступа
    int Get(void) { return number; }
    void Set(int _number) { number = _number; }

    // объявление "дружественной" к классу Integer операторной функции
    // которая перегружает оператор %=
    friend Integer operator%=(Integer& obj1, Integer& obj2);
};

// "дружественная" операторная функция к классу Integer
// в операторную функцию передается ссылка на класс Integer
Integer operator%=(Integer& obj1, Integer& obj2)
{
    obj1.number = obj1.number % obj2.number; // доступ по ссылке
    return obj1;
}

Использование операторной функции operator%=() может быть следующим

// перегрузка сокращенных операторов присваивания +=, -= и т.д.
Integer d1(14), d2(6); // экземпляры класса Integer
int t;

// вызов "дружественной" операторной функции operator%=()
d1 %= d2; // d1.number = d1.number + d2.number
t = d1.Get(); // t = 2

Integer d3(9), d4(5);
d3 %= d4;
t = d3.Get(); // t = 4

 

4. Пример, который демонстрирует перегрузку оператора *= для класса Complex, реализущего комплексное число. Операторная функция реализована внутри класса

В классе Complex реализуется операторная функция, которая перегружает оператор *=. Эта функция реализует умножение комплексных чисел по формуле:

(a+bj)*(c+dj) = (a*c-b*d) + (a*d+b*c)j


Реализация класса Complex

class Complex
{
private:
    double real; // вещественная часть
    double imag; // мнимая часть

public:
    // конструктор класса
    Complex(double _real, double _imag)
    {
        real = _real;
        imag = _imag;
    }

    // методы доступа
    double GetReal(void) { return real; }
    double GetImag(void) { return imag; }

    void Set(double _real, double _imag)
    {
        real = _real;
        imag = _imag;
    }

    // операторная функция, которая перегружает оператор *=
    // функция реализует умножение комплексных чисел
    Complex operator*=(Complex obj)
    {
        double r;
        double i;
        r = real*obj.real - imag*obj.imag;
        i = real*obj.imag + obj.real*imag;
        real = r;
        imag = i;
        return *this;
    }
};

Демонстрация использования операторной функции

// перегрузка сокращенного оператора *=
Complex c1(2,3); // 2+3j
Complex c2(-1,1); // -1+j
double t;

// вызов операторной функции *=
c1 *= c2; // c1 = -5-1j

t = c1.GetReal(); // t = -5
t = c1.GetImag(); // t = -1

 

5. Пример, который демонстрирует перегрузку оператора *= для класса Complex, реализующего комплексное число. Операторная функция реализована как «дружественная» к классу

В примере реализуется операция умножения комплексных чисел с помощью «дружественной» (friend) операторной функции operator*=(). «Дружественная» операторная функция получает 2 параметра.

class Complex
{
private:
    double real; // вещественная часть
    double imag; // мнимая часть

public:
    // конструктор класса
    Complex(double _real, double _imag)
    {
        real = _real;
        imag = _imag;
    }

    // методы доступа
    double GetReal(void) { return real; }
    double GetImag(void) { return imag; }

    void Set(double _real, double _imag)
    {
        real = _real;
        imag = _imag;
    }

    // объявление "дружественной" функции
    friend Complex operator*=(Complex& c1, Complex& c2);
};

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

Использование класса Complex в другом методе может быть следующим:

// перегрузка сокращенного оператора *=
Complex c1(3,-2); // 3-2j
Complex c2(1,-1); // 1-j

double t;

// вызов операторной функции *=
c1 *= c2;

t = c1.GetReal(); // t = -1
t = c1.GetImag(); // t = -5

 

6. Пример, который демонстрирует перегрузку оператора /= для массива чисел типа double. Массив имеет фиксированный размер. Операторная функция реализована внутри класса

В классе ArrayDouble реализуется массив чисел типа double. Операторная функция operator/=() реализует поэлементное деление двух массивов

// фиксированный массив типа double
class ArrayDouble
{
private:
    double D[10]; // массив

public:
    // конструктор
    ArrayDouble()
    {
        for (int i=0; i<10; i++)
            D[i] = 0;
    }

    // методы доступа
    double Get(int index)
    {
        if ((index>=0)&&(index<10))
            return D[index];
        return 0.0;
    }

    void Set(int index, double value)
    {
        if ((index>=0)&&(index<10))
            D[index] = value;
    }

    // операторная функция, поэлементно делит два массива
    ArrayDouble operator/=(ArrayDouble AD)
    {
        // поэлементное деление текущего массива на массив AD
        for (int i=0; i<10; i++)
            D[i] = D[i] / AD.Get(i);
        return *this;
    }
};

Использование класса ArrayDoble может быть таким

// перегрузка сокращенного оператора *=
ArrayDouble A1;
ArrayDouble A2;
double t;

// формирование массивов
for (int i=0; i<10; i++)
    A1.Set(i,10); // A1 = {10,10,10,10,10,10,10,10,10,10}

for (int i=0; i<10; i++) // A2 = {1,2,3,4,5,6,7,8,9,10}
    A2.Set(i, i+1);

// вызов операторной функции
A1 /= A2;

// проверка
t = A1.Get(0); // t = 10/1 = 10.0
t = A1.Get(1); // t = 10/2 = 5.0
t = A1.Get(2); // t = 10/3 = 3.33333333
t = A1.Get(7); // t = 10/8 = 1.25

 

7. Пример, который демонстрирует перегрузку оператора /= для массива чисел типа double. Массив имеет фиксированный размер. Операторная функция реализована как «дружественная» к классу

В классе ArrayDouble объявляется «дружественная» операторная функция, которая реализует поэлементное деление массивов. Объявление класса ArrayDouble и операторной функции следующее

// фиксированный массив типа double
class ArrayDouble
{
private:
    double D[10]; // массив

public:
    // конструктор
    ArrayDouble()
    {
        for (int i=0; i<10; i++)
            D[i] = 0;
    }

    // методы доступа
    double Get(int index)
    {
        if ((index>=0)&&(index<10))
            return D[index];
        return 0.0;
    }

    void Set(int index, double value)
    {
        if ((index>=0)&&(index<10))
            D[index] = value;
    }

    // объявление "дружественной" операторной функции
    friend ArrayDouble operator/=(ArrayDouble& AD1, ArrayDouble& AD2);
};

// реализация "дружественной" к классу ArrayDouble операторной функции
ArrayDouble operator/=(ArrayDouble& AD1, ArrayDouble& AD2)
{
    for (int i=0; i<10; i++)
        AD1.D[i] = AD1.D[i] / AD2.D[i];
    return AD1;
}

Использование класса в другом программном коде

// перегрузка сокращенного оператора *=
ArrayDouble A1;
ArrayDouble A2;
double t;

// формирование массивов
for (int i=0; i<10; i++)
    A1.Set(i,10); // A1 = {10,10,10,10,10,10,10,10,10,10}

for (int i=0; i<10; i++) // A2 = {1,2,3,4,5,6,7,8,9,10}
    A2.Set(i, i+1);

// вызов "дружественной" операторной функции
A1 /= A2;

// проверка
t = A1.Get(0); // t = 10/1 = 10.0
t = A1.Get(1); // t = 10/2 = 5.0
t = A1.Get(2); // t = 10/3 = 3.33333333
t = A1.Get(7); // t = 10/8 = 1.25

 

8. Пример, который демонстрирует несколько вариантов перегрузки оператора += для класса Point. Операторная функция operator+=() есть перегруженной и реализована внутри класса

Операторные функции в классе могут быть перегружены. Такие функции должны содержать одинаковое количество параметров, но эти параметры должны иметь разные типы.

// Класс, который реализует точку на координатной плоскости
// класс содержит две перегруженные операторные функции operator+=()
class Point
{
private:
    int x, y; // координаты точки

public:
    // конструкторы класса
    Point()
    {
        x = y = 0;
    }

    Point(int nx, int ny)
    {
        x = nx;
        y = ny;
    }

    // методы доступа к членам класса
    int GetX(void) { return x; }
    int GetY(void) { return y; }
    void SetX(int nx) { x = nx; }
    void Set(int ny) { y = ny; }

    // операторная функция '+='
    // которая суммирует 2 точки
    Point operator+=(Point pt)
    {
        x = x + pt.x;
        y = y + pt.y;
        return *this;
    }

    // операторная функция '+='
    // которая увеличивает x и y на величину входного параметра d
    Point operator+=(int d)
    {
        x = x + d;
        y = y + d;
        return *this;
    }
};

В вышеприведенном коде реализованы две операторные функции operator+=(), которые перегружают оператор +=.

// операторная функция '+='
// которая суммирует 2 точки
Point operator+=(Point pt)
{
    // ...
}

// операторная функция '+='
// которая увеличивает x и y на величину входного параметра d
Point operator+=(int d)
{
    // ...
}

Ниже продемонстрировано использование операторных функций класса Point.

// перегрузка сокращенного оператора +=
Point p1(2,3);
Point p2(4,5);
int x, y;

// вызов операторной функции суммирования экземпляров типа Point
p1 += p2;

// проверка
x = p1.GetX(); // x = 2+4 = 6
y = p1.GetY(); // y = 3+5 = 8

p2 += p1;
x = p2.GetX(); // x = 6+4 = 10
y = p2.GetY(); // y = 8+5 = 13

// вызов операторной функции суммирования Point + int
p1 += 10;
x = p1.GetX(); // x = 6+10 = 16
y = p1.GetY(); // y = 8+10 = 18

//
Point p3(5,5);
p3+=-7;
x = p3.GetX(); // x = -2
y = p3.GetY(); // y = -2

 


Связанные темы