w C++ przeciążenie operatora jest polimorfizmem występującym w czasie kompilacji. Jest to pomysł na nadanie specjalnego znaczenia istniejącemu operatorowi w C++ bez zmiany jego pierwotnego znaczenia.
W tym artykule omówimy dalej na przykładach przeciążanie operatorów w C++ i zobaczymy, które operatory możemy, a których nie możemy przeciążać w C++.
Przeciążenie operatora C++
C++ ma możliwość nadawania operatorom specjalnego znaczenia dla typu danych. Zdolność ta nazywana jest przeciążaniem operatora. Przeciążanie operatorów jest polimorfizmem występującym w czasie kompilacji. Na przykład możemy przeciążyć operator „+” w klasie takiej jak String, abyśmy mogli połączyć dwa ciągi za pomocą samego znaku +. Inne przykładowe klasy, w których operatory arytmetyczne mogą być przeciążone, to liczby zespolone, liczby ułamkowe, duże liczby całkowite itp.
Przykład:
int a; float b,sum; sum = a + b;>
Tutaj zmienne aib są typu int i float, które są wbudowanymi typami danych. Stąd operator dodawania „+” może łatwo dodać zawartość a i b. Dzieje się tak, ponieważ operator dodawania + jest predefiniowany do dodawania wyłącznie zmiennych o wbudowanym typie danych.
Realizacja:
C++
// C++ Program to Demonstrate the> // working/Logic behind Operator> // Overloading> class> A {> >statements;> };> int> main()> {> >A a1, a2, a3;> >a3 = a1 + a2;> >return> 0;> }> |
złamać Javę
>
>
W tym przykładzie mamy 3 zmienne a1, a2 i a3 typu klasy A. Tutaj próbujemy dodać dwa obiekty a1 i a2, które są typu zdefiniowanego przez użytkownika, tj. typu klasy A za pomocą operatora +. Nie jest to dozwolone, ponieważ operator dodawania + jest predefiniowany do działania wyłącznie na wbudowanych typach danych. Ale tutaj klasa A jest typem zdefiniowanym przez użytkownika, więc kompilator generuje błąd. W tym miejscu pojawia się koncepcja przeciążenia operatora.
Teraz, jeśli użytkownik chce, aby operator + dodał dwa obiekty klas, musi na nowo zdefiniować znaczenie operatora + w taki sposób, aby dodał dwa obiekty klas. Odbywa się to poprzez wykorzystanie koncepcji przeciążenia operatora. Zatem główną ideą przeciążania operatorów jest użycie operatorów C++ ze zmiennymi klasowymi lub obiektami klas. Przedefiniowanie znaczenia operatorów tak naprawdę nie zmienia ich pierwotnego znaczenia; zamiast tego nadano im dodatkowe znaczenie wraz z istniejącymi.
Przykład przeciążania operatorów w 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();> }> |
>
>Wyjście
12 + i9>
Różnica między funkcjami operatora a funkcjami normalnymi
Funkcje operatora są takie same jak normalne funkcje. Jedyna różnica polega na tym, że nazwa funkcji operatora to zawsze słowo kluczowe operatora po którym następuje symbol operatora, a funkcje operatora są wywoływane, gdy używany jest odpowiedni operator.
Przykład
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;> }> |
>
>
losowa liczba w JavieWyjście
12 + i9>
Czy możemy przeciążyć wszystkich operatorów?
Prawie wszyscy operatorzy mogą być przeciążeni, z wyjątkiem kilku. Poniżej znajduje się lista operatorów, których nie można przeciążać.
sizeof typeid Scope resolution (::) Class member access operators (.(dot), .* (pointer to member operator)) Ternary or conditional (?:)>
Operatory, które można przeciążać w C++
Możemy przeciążać
Operatory jednoargumentowe Operatory binarne Operatory specjalne ( [ ], () itp.)
Ale wśród nich są operatory, których nie można przeciążać. Oni są
Operator rozpoznawania zakresu (: operator wyboru członka Wybór członka poprzez *
Wskaźnik do zmiennej członkowskiej
- Operator warunkowy (? Sizeof operator sizeof()
| Operatory, które mogą być przeciążone | Przykłady |
|---|---|
| Arytmetyka binarna | +, -, *, /, % |
| Arytmetyka jednoargumentowa | +, -, ++, — |
| Zadanie | =, +=,*=, /=,-=, %= |
| Bitowe | &, | , <> , ~ , ^ |
| Usuwanie odnośników | (->) |
| Dynamiczna alokacja pamięci, De-alokacja | Nowy, usuń |
| Indeks | [ ] |
| Wywołanie funkcji | () |
| Logiczny | &, | |,! |
| Relacyjny | >, <, = =, = |
Dlaczego powyższe operatory nie mogą być przeciążone?
1. rozmiar Operatora
Zwraca to rozmiar obiektu lub typ danych wprowadzony jako operand. Jest to oceniane przez kompilator i nie może być oceniane w czasie wykonywania. Prawidłowe zwiększanie wskaźnika w tablicy obiektów zależy pośrednio od operatora sizeof. Zmiana jego znaczenia za pomocą przeciążenia spowodowałaby załamanie się podstawowej części języka.
2. wpisz Operator
Zapewnia to programowi CPP możliwość odzyskania faktycznie wyprowadzonego typu obiektu, do którego odnosi się wskaźnik lub odwołanie. W przypadku tego operatora chodzi o jednoznaczną identyfikację typu. Jeśli chcemy, aby typ zdefiniowany przez użytkownika „wyglądał” jak inny typ, można zastosować polimorfizm, ale znaczenie operatora typeid musi pozostać niezmienione, w przeciwnym razie mogą pojawić się poważne problemy.
3. Rozdzielczość zakresu (::) Operator
Pomaga to zidentyfikować i określić kontekst, do którego odnosi się identyfikator, poprzez określenie przestrzeni nazw. Jest całkowicie oceniany w czasie wykonywania i działa na nazwach, a nie na wartościach. Operandy rozpoznawania zakresu są wyrażeniami typu uwaga z typami danych, a CPP nie ma składni umożliwiającej ich przechwytywanie, gdyby był przeciążony. Zatem syntaktycznie niemożliwe jest przeciążenie tego operatora.
4. Operatory dostępu członków klasy (.(kropka ), .* (wskaźnik do operatora członkowskiego))
Znaczenie i ukryte użycie operatorów dostępu członków klasy można zrozumieć na następującym przykładzie:
Przykład:
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>->prawdziwy = prawdziwy;> >this>->wyimaginowany = wyimaginowany;> >}> >void> print() { cout << real <<>' + i'> << imaginary; }> >ComplexNumber operator+(ComplexNumber c2)> >{> >ComplexNumber c3(0, 0);> >c3.real =>this>->prawdziwy + c2.rzeczywisty;> >c3.imaginary =>this>->wyimaginowany + c2.wyimaginowany;> >return> c3;> >}> };> int> main()> {> >ComplexNumber c1(3, 5);> >ComplexNumber c2(2, 4);> >ComplexNumber c3 = c1 + c2;> >c3.print();> >return> 0;> }> |
>
>Wyjście
5 + i9>
Wyjaśnienie:
Instrukcja ComplexNumber c3 = c1 + c2; jest wewnętrznie tłumaczone jako ComplexNumber c3 = c1.operator+ (c2); w celu wywołania funkcji operatorskiej. Argument c1 jest przekazywany niejawnie za pomocą metody „.” operator. Następna instrukcja również korzysta z operatora kropki, aby uzyskać dostęp do funkcji składowej print i przekazać c3 jako argument.
Poza tym operatory te działają również na nazwach, a nie na wartościach i nie ma możliwości (syntaktycznego) ich przeciążania.
5. Operator trójskładnikowy lub warunkowy (?:)
Operator trójskładnikowy lub warunkowy jest skróconą reprezentacją instrukcji if-else. W operatorze wyrażenia prawda/fałsz są oceniane wyłącznie na podstawie wartości logicznej wyrażenia warunkowego.
conditional statement ? expression1 (if statement is TRUE) : expression2 (else)>
Funkcja przeciążająca operator trójskładnikowy dla klasy mówi ABC, korzystając z definicji
ABC operator ?: (bool condition, ABC trueExpr, ABC falseExpr);>
nie byłby w stanie zagwarantować, że zostało ocenione tylko jedno z wyrażeń. Zatem operator trójskładnikowy nie może być przeciążony.
Ważne uwagi dotyczące przeciążenia operatora
1) Aby przeciążenie operatora zadziałało, co najmniej jeden z operandów musi być obiektem klasy zdefiniowanym przez użytkownika.
przykład listy w Javie
2) Operator przypisania: Kompilator automatycznie tworzy domyślny operator przypisania dla każdej klasy. Domyślny operator przypisania przypisuje wszystkie elementy prawej strony do lewej i w większości przypadków działa dobrze (to zachowanie jest takie samo jak w przypadku konstruktora kopiującego). Zobacz to, aby uzyskać więcej szczegółów.
3) Operator konwersji: Możemy także napisać operatory konwersji, których można użyć do konwersji jednego typu na inny.
Przykład:
C++
dziedziczenie w Javie
// 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;> }> |
>
>Wyjście
0.4>
Przeciążone operatory konwersji muszą być metodą członkowską. Innymi operatorami mogą być metody członkowskie lub metody globalne.
4) Dowolny konstruktor, który można wywołać z pojedynczym argumentem, działa jako konstruktor konwersji, co oznacza, że można go również użyć do niejawnej konwersji do konstruowanej klasy.
Przykład:
C++
// 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;> }> |
>
>Wyjście
x = 20, y = 20 x = 30, y = 0>
Quiz na temat przeciążenia operatora