Przeciążanie operatorów w C++

Podczas mojego pierwszego spotkania z C++ zauważyłem, że moim kolegom z roku sprawia problem temat przeciążania operatorów. Wtedy też napisałem prosty przykład tego mechanizmu, który w tym wpisie chciałbym odrobinę szerzej opisać.
W ramach przykładu utwórzmy klasę MyInt, która tak naprawdę będzie zawierała
tylko pole typu int
z wartością całkowitą oraz dwa konstruktory (jeden bez parametrów,
który wpisuje w pole val
wartość 0
oraz drugi, który w to pole wpisuje
podaną w parametrze wartość):
#include <iostream>
using namespace std;
class MyInt {
public:
/* Pole val */
int val;
/* Konstruktory */
MyInt();
MyInt(int x);
};
/* Definicje konstruktorów */
MyInt::MyInt(){
val = 0;
}
MyInt::MyInt(int x) {
val = x;
}
main() {
MyInt one(1), two(2);
cout << one.val << endl;
cout << two.val << endl;
MyInt three(one.val + two.val);
cout << three.val << endl;
return 0;
}
Co jednak jeśli chcielibyśmy mieć możliwość dodawania ich w równie prosty sposób
co dodawać dwie typu int
? Musimy wtedy przeciążyć operator dodawania. W tym celu
dodajmy następującą metodę do naszego kodu:
MyInt MyInt::operator+(const MyInt operand) {
MyInt wynik = *this;
wynik.val = operand.val + wynik.val;
return wynik;
}
Jak widać przeciążanie tego typu operatora jest proste - w identyczny sposób możemy
przeciążyć na przykład -
, wystarczy zamienić operator+
na operator-
. Jednak nie
jest to raczej dobrym pomysłem aby pod odejmowanie przypisać dodawanie. ;-)
Warte zapamiętania jest to, że pierwszym operandem jest this
, natomiast drugi
przekazujemy. Czyli gdy zapiszemy a + b
to a
będzie this
, natomiast b
przekażemy
do funkcji jako parametr operand
.
Dzięki tym kilku linijkom kodu możemy uprościć operowanie naszą klasą i dodawanie dwóch elementów zapisać w ten sposób:
MyInt three = one + two;
Kolejną rzeczą jaką chcemy uzyskać to przeciążenie operatora <<
, aby mieć możliwość
wypisania wartości naszego MyInt
przy pomocy konstrukcji cout << one
. W tym celu
musimy utworzyć następującą funkcję, która nie jest częścią naszej klasy:
ostream& operator<<(ostream &out, const MyInt& myint) {
return out << "Wartosc: " << myint.val;
}
Teraz jeśli napiszemy cout << one
to na wyjście zostanie wypisane Wartosc: 1
- czyli
dokładnie tak jak chcieliśmy.
Jest to jednak możliwe tylko w przypadku gdy odwołujemy się do pola publicznego danej klasy. Co jednak gdy nasze pole jest prywatne? Nasza klasa wygląda wtedy następująco:
class MyInt {
private:
/* Pole val */
int val;
public:
/* Konstruktory */
MyInt();
MyInt(int x);
MyInt operator+(const MyInt operand);
};
Musimy wtedy zaprzyjaźnić (friend
) funkcje z naszą klasą aby miała ona dostęp do
prywatnych składowych naszej klasy. Możemy to zrobić dodając do naszej klasy następującą linijkę:
friend ostream& operator<<(ostream &out, const MyInt& myint);
Tym sposobem możemy tak samo jak wyżej korzystać z operatora <<
przy wypisywaniu
bez względu na to, że nasze pole jest prywatne. :-)
Mam nadzieję, że ten wpis rozjaśnia trochę jak przeciąża się operatory w C++. :-) Oczywiście kod obu przykładów jest dostępny w serwisie GitHub tutaj. Jeśli masz jakieś wątpliwość lub pytania - napisz w komentarzu, postaram się odpowiedzieć. Do następnego! ;-)
comments powered by Disqus