Перегрузка сокращенных операторов присваивания +=, -=, *=, /=, %=. Примеры
Данная тема базируется на изучении следующих тем
- Перегрузка операторов в C++. Операторная функция. Ключевое слово operator. Перегрузка базовых арифметических операторов +, –, *, /. Примеры реализации встроенных операторных функций
- «Дружественные» операторные функции: отличия, реализации, особенности применения. Перегрузка операторов +, –, *, / с помощью «дружественных» операторных функций
Содержание
- 1. Особенности перегрузки сокращенных операторов присваивания +=, -=, *=, /=, %=. Общая форма операторной функции
- 2. Пример, который демонстрирует перегрузку оператора += для класса Integer, который реализует целое число. Операторная функция объявляется внутри класса
- 3. Пример, который демонстрирует перегрузку оператора %= для класса Integer, который реализует целое число. Операторная функция объявляется как «дружественная» к классу Integer
- 4. Пример, который демонстрирует перегрузку оператора *= для класса Complex, реализущего комплексное число. Операторная функция реализована внутри класса
- 5. Пример, который демонстрирует перегрузку оператора *= для класса Complex, реализующего комплексное число. Операторная функция реализована как «дружественная» к классу
- 6. Пример, который демонстрирует перегрузку оператора /= для массива чисел типа double. Массив имеет фиксированный размер. Операторная функция реализована внутри класса
- 7. Пример, который демонстрирует перегрузку оператора /= для массива чисел типа double. Массив имеет фиксированный размер. Операторная функция реализована как «дружественная» к классу
- 8. Пример, который демонстрирует несколько вариантов перегрузки оператора += для класса Point. Операторная функция operator+=() есть перегруженной и реализована внутри класса
- Связанные темы
Поиск на других ресурсах:
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
⇑
Связанные темы
- 1. Перегрузка операторов в C++. Операторная функция. Ключевое слово operator. Перегрузка базовых арифметических операторов +, –, *, /. Примеры реализации встроенных операторных функций
- 2. «Дружественные» операторные функции: отличия, реализации, особенности применения. Перегрузка операторов +, –, *, / с помощью «дружественных» операторных функций
- 3. Перегрузка инкрементных и декрементных операторов ++, —. Примеры