c0ffee.pl

o kodzie przy kubku kawy

Witaj na moim blogu! Jestem Kamil, na codzień zajmuje się pisaniem kodu w Javie (i nie tylko). Więcej o mnie możesz znaleźć na mojej stronie.

Przeciążanie operatorów w C++

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ć.

Jeśli chcesz przejść od razu do kodu to można go znaleźć tutaj.

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ść):

C++
#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:

C++
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:

C++
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:

C++
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:

C++
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ę:

C++
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! ;-)

Opublikowano:
comments powered by Disqus

Wszystkie wpisy, które tutaj znajdziesz są pod licencją CC BY-NC 4.0.

Strona korzysta z ciasteczek. Po więcej informacji zajrzyj w pomoc dostarczaną przez producenta Twojej przeglądarki.