C++ Przeładowanie operatorów i wzorce w klasach
Transkrypt
C++ Przeładowanie operatorów i wzorce w klasach
Przeładowanie operatorów Wzorce w klasach C++ Przeładowanie operatorów i wzorce w klasach Andrzej Przybyszewski numer albumu: 89810 14 listopada 2009 Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Ogólnie Przeładowanie operatorów Przeładowanie (przeciążanie) operatorów polega na nadaniu im nowych funkcji. Przeładowanie operatora dokonuje się definiując swoją własną funkcję która: Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Ogólnie Przeładowanie operatorów Przeładowanie (przeciążanie) operatorów polega na nadaniu im nowych funkcji. Przeładowanie operatora dokonuje się definiując swoją własną funkcję która: nazywa się operator@ gdzie znaczek @ to symbol operatora, o którego przeładowanie nam chodzi (np. +,-,* itp.) Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Ogólnie Przeładowanie operatorów Przeładowanie (przeciążanie) operatorów polega na nadaniu im nowych funkcji. Przeładowanie operatora dokonuje się definiując swoją własną funkcję która: nazywa się operator@ gdzie znaczek @ to symbol operatora, o którego przeładowanie nam chodzi (np. +,-,* itp.) jako co najmniej jeden z argumentów, przyjmuje obiekt danej klasy lub referencję do takiego obiektu. Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Ogólnie Przeładowanie operatorów Przeładowanie (przeciążanie) operatorów polega na nadaniu im nowych funkcji. Przeładowanie operatora dokonuje się definiując swoją własną funkcję która: nazywa się operator@ gdzie znaczek @ to symbol operatora, o którego przeładowanie nam chodzi (np. +,-,* itp.) jako co najmniej jeden z argumentów, przyjmuje obiekt danej klasy lub referencję do takiego obiektu. Nie możemy przeładowywać operatorów dla typów wbudowanych (int, char, float). Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Konstrukcja Przeładowanie operatorów Konstrukcja: typ_zwracany operator@ (argumenty) { // operacje } Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Operatory Przeładowanie operatorów Operatory które można przeładować: + - * / % & | ^ << << ~ && || ! == != < <= > >= += -= *= /= %= &= |= ^= <<= >>= ++ -- = -> ->* () [] new delete , Trzeba zapamiętać że można przeciążać TYLKO te operatory. Próba przeciążania innych (jak i tworzenia nowych jak np @) skończy się błędem. Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Operatory Przeładowanie operatorów Operatory które można przeładować: + - * / % & | ^ << << ~ && || ! == != < <= > >= += -= *= /= %= &= |= ^= <<= >>= ++ -- = -> ->* () [] new delete , Trzeba zapamiętać że można przeciążać TYLKO te operatory. Próba przeciążania innych (jak i tworzenia nowych jak np @) skończy się błędem. NIE można zmieniać priorytetu wykonywania tych operatorów! np. a + b + c zostanie wykonane zgodnie z matematycznym punktem widzenia (a + b) + c, za to a + b * c jako a + (b * c) w tym wypadku. Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Przykład - liczby zespolone 1 Przeładowanie operatorów Przykład: class LZESPOLONA{ public: LZESPOLONA(); LZESPOLONA(float, float); LZESPOLONA operator+(LZESPOLONA); LZESPOLONA operator-(LZESPOLONA); LZESPOLONA operator*(LZESPOLONA); LZESPOLONA operator+=(LZESPOLONA); LZESPOLONA operator-=(LZESPOLONA); LZESPOLONA operator*=(LZESPOLONA); private: float a; float b; }; Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Przykład - liczby zespolone 2 Przeładowanie operatorów Mamy daną klasę definiującą liczbę zespoloną, gdzie a to część rzeczywista a b to część urojona. Jak widać mamy podane w sekcji public funkcje przeładowujące operatory arytmetyczne. Przykład: //konstruktory LZESPOLONA::LZESPOLONA(float a1, float b1) {a = a1; b = b1;} LZESPOLONA::LZESPOLONA() {a = 0; b = 0;} Chcemy teraz wykonywać działania na tych liczbach bez wielokrotnego dobierania się do składowych a i b i wykonywania nieco żmudnego podstawiania do wzorów. Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Przykład - liczby zespolone 3 Przeładowanie operatorów Przykład: LZESPOLONA LZESPOLONA::operator+( LZESPOLONA B) { return LZESPOLONA(a+B.a, b+B.b); } LZESPOLONA LZESPOLONA::operator-( LZESPOLONA B) {return LZESPOLONA(a-B.a, b-B.b); } W prosty sposób przeładowaliśmy operatory + i - dzięki czemu można wykonać dodawanie i odejmowanie liczb zespolonych. Przedstawiony sposób odnosi się do funcji operatorowych jako niestatycznych składowych klasy, przyjmuje ona wtedy tylko jeden parametr dla operatorów dwuargumentowych. Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Przykład - liczby zespolone 4 Przeładowanie operatorów Możemy także mieć funkcje operatorowe jako funkcje nie-składowe(globalne) wtedy potrzebujemy dwóch argumentów: Przykład: LZESPOLONA operator+(LZESPOLONA A, LZESPOLONA B) { return LZESPOLONA(A.a+B.a, A.b+B.b); } LZESPOLONA operator*(LZESPOLONA A, LZESPOLONA B) { return LZESPOLONA((A.a*B.a-B.b*A.b),(A.b*B.a+A.a*B.b); } Taką funkcję możemy dołączyć do klasy za pomocą friend, lub nie musi być ona składową klasy, jeżeli potrafi wykonywać operacje na obiektach danej klasy. Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Przykład - liczby zespolone 5 Przeładowanie operatorów Kożystając z operatorów arytmetycznych warto zdefiniować sobie operatory wykonujące operacje+przypisanie(dopisanie) czyli np. += , -= , *= , działają one tak jak a = a + b , jak widać zamiast przepisywać a do którego chcemy dopisać coś, można użyć a+=b, definiując nową klasę takie operatory trzeba również zdefiniować (np. jeżeli przeładujemy operator+ to nie stworzy nam się domyślnie działający += co mogłoby się czasem wydawać). Przykład: LZESPOLONA LZESPOLONA::operator+=( LZESPOLONA B) {a = a + B.a; b = b + B.b;} LZESPOLONA LZESPOLONA::operator-=( LZESPOLONA B) {a = a - B.a; b = b - B.b;} Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Przykład - liczby zespolone 6 Przeładowanie operatorów Jak wcześniej pokazano przeładować możemy wiele operatorów (niektórych nie można ale są one raczej mało istotne), każdemu operatorowi możemy nadać nowe właściwości, niekoniecznie musi on robić coś pochodnego od macierzystego przeznaczenia (+ niekoniecznie musi coś dodawać, wszystko zależy od nas). Mały przykład: int main(){ LZESPOLONA a(3,2), b(8, 12.3),c; c = a + b; c = a - b; c += a; //itp... } Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Ogólnie Wzorce w klasach Wzorce są jednym z najsilniejszych narzędzi. Zgodnie ze swoim przeznaczeniem, powinny służyć do tego, aby maksymalnie skrócić konieczność pisania i powtarzania tych samych sekwencji. Wzorce ściśle się trzymają konwencji języka, czego konsekwencją jest to, że mamy do dyspozycji dwa podstawowe rodzaje wzorców: wzorzec funkcji i wzorzec klasy. Definicja wzorca: template < parametry-wzorca > definicja-wzorca Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Wzorce we wzorcach Wzorce w klasach Parametry wzorca są wyjątkowo w nawiasach ostrych. Parametry te przypominają właściwie argumenty funkcji, z tym, że na liście parametrów może wystąpić parametr typu, który zazwyczaj nazywa się class. Oczywiście parametr wzorca może być również np. typu size_t, ale class jest to niewątpliwie wzorców najmocniejsza strona. Jeśli chodzi o kwestie składniowe to: jeśli jednym z parametrów wzorca jest jakiś inny konkretyzowany wzorzec, to NIGDY nie wolno pisać: Definicja wzorca: wz1<costam,wz2<int>> Należy pisać pamiętając żeby rozdzielać ostre nawiasy: > >. Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Wzorce funkcji i klas Wzorce w klasach Wzorce(szablony) można zastosować do funckji jak i klas(struktur). Wzorzec funkcji: template <class T> inline const T& Min( const T& t1, const T& t2 ) { if ( t1 < t2 ) return t1; return t2; } Wzorzec funkcji inline Min która zwraca element mniejszy. Powinniśmy dostać z tego wzorca: Wzorzec funkcji: inline const int& Min( const int&, const int& ); Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Wzorce klas 1 Wzorce w klasach Zajmijmy się szablonami klas. Wzorzec klasy: template <class parametr> class figura {parametr wysokosc; parametr krawedz1; parametr krawedz2;}; Do szablonu podajemy klasę jakąś, potem możemy ją wykorzystać w nowej klasie tworzonej w szablonie. Tak możemy stworzyć nową klasę figura której parametry są typu int. nowy obiekt: figura<int> trapez; Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Wzorce klas 2 Wzorce w klasach Rozbuduwując naszą klasę we wzrocu: Wzorzec klasy: template <class parametr> class figura { private: parametr wysokosc; ... //inne parametry public: parametr wez_wysokosc (); ... // reszta funkcji zwracających void wpisz_wysokosc (parametr); ... //reszta funkcji wypisujących}; Mamy tu kilka funkcji, trzeba je teraz oprogramować. Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Wzorce klas 3 Wzorce w klasach Zaimplementujmy teraz funkcje w szablonie klasy: Funkcje szablonu klasy: template<class parametr> parametr figura<parametr>::wez_wysokosc () { return wysokosc; } ... // reszta funkcji typu parametr template<class parametr> void figura<parametr>::wpisz_wysokosc (parametr wys) { wysokosc = wys; } ... //reszta funkcji Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Wzorce klas 4 Wzorce w klasach Definicja funkcji składowej szablonu klasy trochę przypomina definicję szablonu funkcji. Zaczynamy od słówka template i nawiasów trójkątnych zawierających parametry szablonu. Następnie podajemy rezultat zwracany przez definiowaną funkcję. Dalej jest nazwa klasy wraz z nawiasami trójkątnymi. W nich ponownie umieszczamy wszystkie parametry szablonu. Kolejny jest operator zakresu i wreszcie nazwa funkcji. Zauważmy jednak, że po nazwie funkcji podajemy jedynie nazwę parametru! Niema tam już słówka class. Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Klasy specjalizowane Wzorce w klasach Specjalizowana wersja szablonu klas, jest to specjalna definicja klasy która zostanie dopasowana przez szablon gdy nastąpi odpowiednie wywołanie. Czyli np. dla typu int* możemy napisać osobną klasę która zostanie utworzona poprzez szablon: Funkcje szablonu klasy: class figura<int *> { //składniki szablonu klas }; //funkcja składowa void figura<int*>::wpisz_wysokosc (int * wys) { wysokosc = *wys; } Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach Nowy obiekt Wzorce w klasach Jak wcześniej wspomniano, mając już cały szablon klasy, możemy na jego podstawie utworzyć nowy obiekt np. klasy utworzonej wcześniej z liczb zespolonych: Funkcje szablonu klasy: figura<LZESPOLONA> kwadrat; kwadrat.wpisz_wysokosc(LZESPOLONA(2, 4)); //oczywiście figura i liczby zespolone //nie za bardzo do siebie pasują Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach Przeładowanie operatorów Wzorce w klasach STL Wzorce w klasach W standardzie języka C++ wprowadzono biblioteki standardowych szablonów, są to szablony na podstawie których możemy tworzyć najczęstsze struktury danych, na podstawie dowolnych obiektów. Niektóre elementy STL’a: Vector: vector<LZESOPLONA> zesptab;//tablica dynamiczna List: list<LZESPOLONA> listazesp;//lista dwukierunkowa Stack: stack<ZESPOLONA> zespstos;//stos Andrzej Przybyszewski numer albumu: 89810 C++Przeładowanie operatorów i wzorce w klasach