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