Перевантаження скорочених операторів присвоювання. Приклади

Перевантаження скорочених операторів присвоювання +=, -=, *=, /=, %=. Приклади

Дана тема базується на вивченні попередніх тем


Зміст



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; // d.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 SetY(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

 


Зв’язані теми