logo

Перевантаження операторів у C++

у C++ перевантаження операторів є поліморфізмом під час компіляції. Це ідея надання особливого значення існуючому оператору в C++ без зміни його початкового значення.

У цій статті ми далі обговоримо перевантаження операторів у C++ із прикладами та побачимо, які оператори ми можемо, а які не можна перевантажувати в C++.



Перевантаження оператора C++

C++ має можливість надавати операторам особливе значення для типу даних, ця здатність відома як перевантаження операторів. Перевантаження операторів є поліморфізмом під час компіляції. Наприклад, ми можемо перевантажити оператор «+» у такому класі, як String, щоб ми могли об’єднати два рядки, просто використовуючи +. Іншими прикладами класів, де арифметичні оператори можуть бути перевантажені, є комплексні числа, дробові числа, великі цілі числа тощо.

приклад:

int a; float b,sum; sum = a + b;>

Тут змінні a і b мають типи int і float, які є вбудованими типами даних. Отже, оператор додавання «+» може легко додати вміст a і b. Це тому, що оператор додавання + попередньо визначено для додавання змінних лише вбудованого типу даних.



Реалізація:

C++






містить підрядок java
// C++ Program to Demonstrate the> // working/Logic behind Operator> // Overloading> class> A {> >statements;> };> int> main()> {> >A a1, a2, a3;> >a3 = a1 + a2;> >return> 0;> }>

>

>

У цьому прикладі ми маємо 3 змінні a1, a2 і a3 класу типу A. Тут ми намагаємося додати два об’єкти a1 і a2, які мають тип, визначений користувачем, тобто клас типу A за допомогою оператора +. Це неприпустимо, оскільки оператор додавання + попередньо визначено для роботи лише з вбудованими типами даних. Але тут клас A є типом, визначеним користувачем, тому компілятор генерує помилку. Ось тут і виникає концепція перевантаження оператора.

Тепер, якщо користувач хоче змусити оператор + додати два об’єкти класу, користувач має перевизначити значення оператора + таким чином, щоб він додавав два об’єкти класу. Це робиться за допомогою концепції перевантаження оператора. Отже, основна ідея перевантаження операторів полягає у використанні операторів C++ зі змінними класу або об’єктами класу. Перевизначення значення операторів насправді не змінює їх початкове значення; натомість їм надали додаткового значення разом із уже існуючими.

Приклад перевантаження операторів у C++

C++




// C++ Program to Demonstrate> // Operator Overloading> #include> using> namespace> std;> class> Complex {> private>:> >int> real, imag;> public>:> >Complex(>int> r = 0,>int> i = 0)> >{> >real = r;> >imag = i;> >}> >// This is automatically called when '+' is used with> >// between two Complex objects> >Complex operator+(Complex>const>& obj)> >{> >Complex res;> >res.real = real + obj.real;> >res.imag = imag + obj.imag;> >return> res;> >}> >void> print() { cout << real <<>' + i'> << imag <<>' '>; }> };> int> main()> {> >Complex c1(10, 5), c2(2, 4);> >Complex c3 = c1 + c2;> >c3.print();> }>

>

>

Вихід

12 + i9>

Різниця між функціями оператора та звичайними функціями

Функції оператора такі ж, як і звичайні функції. Єдина відмінність полягає в тому, що ім'я операторної функції завжди є ключове слово оператора після символу оператора, і операторні функції викликаються, коли використовується відповідний оператор.

приклад

C++




#include> using> namespace> std;> class> Complex {> private>:> >int> real, imag;> public>:> >Complex(>int> r = 0,>int> i = 0)> >{> >real = r;> >imag = i;> >}> >void> print() { cout << real <<>' + i'> << imag << endl; }> >// The global operator function is made friend of this> >// class so that it can access private members> >friend> Complex operator+(Complex>const>& c1,> >Complex>const>& c2);> };> Complex operator+(Complex>const>& c1, Complex>const>& c2)> {> >return> Complex(c1.real + c2.real, c1.imag + c2.imag);> }> int> main()> {> >Complex c1(10, 5), c2(2, 4);> >Complex c3> >= c1> >+ c2;>// An example call to 'operator+'> >c3.print();> >return> 0;> }>

ряд фібоначчі в java

>

>

Вихід

12 + i9>

Чи можемо ми перевантажити всіх операторів?

Майже всі оператори можуть бути перевантажені, крім кількох. Нижче наведено список операторів, які не можна перевантажувати.

"формула масона"
sizeof typeid Scope resolution (::) Class member access operators (.(dot), .* (pointer to member operator)) Ternary or conditional (?:)>

Оператори, які можуть бути перевантажені в C++

Ми можемо перевантажити

    Унарні оператори Двійкові оператори Спеціальні оператори ( [ ], () тощо)

Але серед них є оператори, які не можна перевантажувати. Вони є

    Оператор розділення області (: Оператор вибору члена Вибір члена через *

Покажчик на змінну-член

    Умовний оператор (? Оператор Sizeof sizeof()
Оператори, які можуть бути перевантажені Приклади
Двійкова арифметика +, -, *, /, %
Унарна арифметика +, -, ++, —
призначення =, +=,*=, /=,-=, %=
Побітово &, | , <> , ~ , ^
Зняття посилань (->)
Динамічний розподіл пам'яті,
Деалокація
Новий, видалити
Підрядковий [ ]
Виклик функції ()
Логічний &, | |, !
Реляційний >, <, = =, =

Чому вищевказані оператори не можна перевантажувати?

1. розмір оператора

Це повертає розмір об’єкта або типу даних, введеного як операнд. Це оцінюється компілятором і не може бути оцінено під час виконання. Належне збільшення вказівника в масиві об’єктів неявно залежить від оператора sizeof. Зміна його значення за допомогою перевантаження призведе до руйнування фундаментальної частини мови.

2. Оператор typeid

Це надає програмі CPP можливість відновлювати фактично похідний тип об’єкта, на який посилається вказівник або посилання. Для цього оператора суть полягає в унікальній ідентифікації типу. Якщо ми хочемо, щоб визначений користувачем тип «виглядав» як інший тип, можна використовувати поліморфізм, але значення оператора typeid має залишатися незмінним, інакше можуть виникнути серйозні проблеми.

3. Оператор дозволу області (::).

Це допомагає визначити та визначити контекст, до якого посилається ідентифікатор, вказуючи простір імен. Він повністю оцінюється під час виконання та працює з іменами, а не зі значеннями. Операнди розв’язання області – це вирази нот із типами даних, і CPP не має синтаксису для їх захоплення, якщо він перевантажений. Тому синтаксично неможливо перевантажити цей оператор.

4. Оператори доступу членів класу (.(точка ), .* (вказівник на оператор-член))

Важливість і неявне використання операторів доступу до членів класу можна зрозуміти через наступний приклад:

приклад:

C++




// C++ program to demonstrate operator overloading> // using dot operator> #include> using> namespace> std;> class> ComplexNumber {> private>:> >int> real;> >int> imaginary;> public>:> >ComplexNumber(>int> real,>int> imaginary)> >{> >this>->реальний = справжній;> >this>->уявний = уявний;> >}> >void> print() { cout << real <<>' + i'> << imaginary; }> >ComplexNumber operator+(ComplexNumber c2)> >{> >ComplexNumber c3(0, 0);> >c3.real =>this>->дійсний + c2.дійсний;> >c3.imaginary =>this>->уявний + c2.уявний;> >return> c3;> >}> };> int> main()> {> >ComplexNumber c1(3, 5);> >ComplexNumber c2(2, 4);> >ComplexNumber c3 = c1 + c2;> >c3.print();> >return> 0;> }>

>

>

Вихід

5 + i9>

Пояснення:

Оператор КомплекснеЧисло c3 = c1 + c2; внутрішньо транслюється як комплексне число c3 = c1.operator+ (c2); щоб викликати функцію оператора. Аргумент c1 неявно передається за допомогою '.' оператор. Наступний оператор також використовує оператор крапки для доступу до функції-члена print і передає c3 як аргумент.

Крім того, ці оператори також працюють з іменами, а не зі значеннями, і немає можливості (синтаксично) перевантажувати їх.

5. Тернарний або умовний (?:) оператор

Тернарний або умовний оператор є скороченим представленням оператора if-else. В операторі вирази true/false обчислюються лише на основі значення істинності умовного виразу.

conditional statement ? expression1 (if statement is TRUE) : expression2 (else)>

Функція, яка перевантажує тернарний оператор для класу, скажімо, ABC, використовуючи визначення

ABC operator ?: (bool condition, ABC trueExpr, ABC falseExpr);>

не зможе гарантувати, що було обчислено лише один із виразів. Таким чином, тернарний оператор не може бути перевантажений.

Важливі моменти щодо перевантаження оператора

1) Щоб перевантаження операторів працювало, принаймні один із операндів має бути визначеним користувачем об’єктом класу.

екземпляр java

2) Оператор присвоєння: Компілятор автоматично створює оператор присвоювання за замовчуванням для кожного класу. Оператор присвоєння за замовчуванням призначає всі члени правої сторони лівій стороні та працює добре в більшості випадків (ця поведінка така ж, як і конструктор копіювання). Перегляньте це для отримання додаткової інформації.

3) Оператор перетворення: Ми також можемо написати оператори перетворення, які можна використовувати для перетворення одного типу в інший.

приклад:

C++




// C++ Program to Demonstrate the working> // of conversion operator> #include> using> namespace> std;> class> Fraction {> private>:> >int> num, den;> public>:> >Fraction(>int> n,>int> d)> >{> >num = n;> >den = d;> >}> >// Conversion operator: return float value of fraction> >operator>float>()>const> >{> >return> float>(num) />float>(den);> >}> };> int> main()> {> >Fraction f(2, 5);> >float> val = f;> >cout << val <<>' '>;> >return> 0;> }>

>

>

Вихід

0.4>

Перевантажені оператори перетворення мають бути методом-членом. Інші оператори можуть бути або методом-членом, або глобальним методом.

4) Будь-який конструктор, який можна викликати за допомогою одного аргументу, працює як конструктор перетворення, що означає, що його також можна використовувати для неявного перетворення в клас, що створюється.

приклад:

C++


ipconfig для ubuntu



// C++ program to demonstrate can also be used for implicit> // conversion to the class being constructed> #include> using> namespace> std;> class> Point {> private>:> >int> x, y;> public>:> >Point(>int> i = 0,>int> j = 0)> >{> >x = i;> >y = j;> >}> >void> print()> >{> >cout <<>'x = '> << x <<>', y = '> << y <<>' '>;> >}> };> int> main()> {> >Point t(20, 20);> >t.print();> >t = 30;>// Member x of t becomes 30> >t.print();> >return> 0;> }>

>

>

Вихід

x = 20, y = 20 x = 30, y = 0>

Тест про перевантаження операторів