class Zesp
Transkrypt
class Zesp
Funkcje składowe (metody) class Punkt { private: int x, y; public: void Rysuj() { /* rysowanie */ }; class Punkt { private: int x, y; public: void Rysuj(); }; void Punkt::Rysuj() { /* rysowanie */ } definicja funkcji wewnątrz ciała klasy } funkcja otwarta definicja funkcji poza ciałem klasy Wywołanie funkcji składowej Funkcja składowa klasy może być aktywowana (wywołana) tylko na rzecz obiektu tej samej klasy. <nazwa obiektu>.<nazwa_funkcji> (<argumenty>) ; PRZYKŁAD: Punkt p; p.Rysuj(); Funkcja składowa class Zesp { public: Zesp(); Zesp(float a, float b); private: float re, im; }; Zesp::Zesp() { re = im = 0; } Zesp::Zesp(float a, float b) { re = a; im = b; } Problem: klasę Zesp należy uzupełnić o operację dodawania dwóch liczb zespolonych. Funkcja składowa class Zesp { public: Zesp(); Zesp(float a, float b); Zesp dodaj(Zesp z); private: float re, im; }; void main() { Zesp a(0, 1), b(1, 0), c; c = a.dodaj(b); } Zesp::Zesp() { re = im = 0; } Zesp::Zesp(float a, float b) { re = a; im = b; } Zesp Zesp::dodaj(Zesp z) { Zesp wynik; wynik.re = re+z.re; wynik.im = im+z.im; return wynik; } return Zesp(re+z.re, im+z.im); Przykład – wersja strukturalna #include <iostream> using namespace std; // definicja struktury typedef struct zespolone { float re, im; // pola struktury } Zespolone; // dodawanie liczb zespolonych Zespolone dodaj (Zespolone a, Zespolone b) { Zespolone c; c.re = a.re + b.re; c.im = a.im + b.im; return c; } void main() { Zespolone a = {0, 1}, b = {1, 0}, c; c = dodaj(a, b); cout << "c = "<< c.re << " + j" << c.im << endl; } Przykład – wersja obiektowa #include <iostream> using namespace std; class Zesp { public: Zesp() { re = 0; im = 0; } Zesp (float Re, float Im) { re = Re; im = Im; } Zesp dodaj (Zesp z) { return Zesp(re+z.re, im+z.im); } void drukuj() { cout << re << ” + j” << im; } private: float re, im; // pola klasy }; void main() { Zesp a(0, 1), b(1, 0), c; c = a.dodaj(b); c.drukuj(); } Wskaźnik this Wskaźnik this zawiera adres obiektu bieżącego (tzn. obiektu, na rzecz którego wywołano funkcję składową). Wskaźnik ten jest dostępny wyłącznie wewnątrz funkcji składowych niestatycznych. this *this - adres obiektu obiekt (wartość obiektu) Słowo kluczowe this jest stosowane wszędzie tam, gdzie w funkcji składowej istnieje potrzeba zwrócenia wskaźnika na obiekt lub wartości obiektu. return this return *this - adres obiektu obiekt Funkcja składowa i wskaźnik this class Zesp { public: Zesp(); Zesp(float a, float b); private: float re, im; }; Zesp::Zesp() { re = im = 0; } Zesp::Zesp(float a, float b) { re = a; im = b; } Problem: klasę Zesp należy uzupełnić o operację powiększania liczby zespolonej o inną liczbę zespoloną. Zastosowanie wskaźnika this Zesp Zesp::powieksz(Zesp z) { re += z.re; // this->re += z.re; im += z.im; // (*this).im += z.im; return *this; } zwrócenie zmodyfikowanego obiektu void main() { Zesp z1(2, 3), z2(3, 5); z1.powieksz(z2); } Funkcje zaprzyjaźnione Funkcja zaprzyjaźniona z klasą to zwykła funkcja „zewnętrzna” lub funkcja składowa innej klasy, zadeklarowana za pomocą słowa kluczowego friend. Cechy funkcji zaprzyjaźnionej: • nie należy do klasy, nie jest składową klasy (wniosek: nie można odwołać się do niej poprzez nazwę kwalifikowaną) • nie można jej aktywować na rzecz obiektu • otrzymuje jako argument lub zwraca jako wynik obiekt klasy z którą jest zaprzyjaźniona • pod względem dostępu do składowych prywatnych ma takie same prawa jak funkcja składowa • funkcja może być zaprzyjaźniona z wieloma klasami (obiekty tych klas to argumenty lub wynik funkcji) Funkcja składowa czy zaprzyjaźniona? class Zesp { public: Zesp(); Zesp(float a, float b); private: float re, im; }; Zesp::Zesp() { re = im = 0; } Zesp::Zesp(float a, float b) { re = a; im = b; } Problem: klasę Zesp należy uzupełnić o operację wydruku liczby zespolonej. Funkcja składowa ROZWIĄZANIE 1: class Zesp { public: Zesp(); Zesp(float a, float b); float get_re(); float get_im(); private: float re, im; }; funkcje udostępniające Zesp::Zesp() { re = im = 0; } Zesp::Zesp(float a, float b) { re = a; im = b; } float Zesp::get_re() { return re; } float Zesp::get_im() { return im; } void main() { Zesp z(2, 5); cout << ‘(‘ << z.get_re() << ‘,‘ << z.get_im() << ‘)‘; } Funkcja składowa ROZWIĄZANIE 2: class Zesp { public: Zesp(); Zesp(float a, float b); void drukuj(); private: float re, im; }; void main() { Zesp z(2, 5); z.drukuj(); } Zesp::Zesp() { re = im = 0; } Zesp::Zesp(float a, float b) { re = a; im = b; } void Zesp::drukuj() { cout << ‘(‘ << re << ‘,‘; cout << im << ‘)‘; } Funkcja zaprzyjaźniona ROZWIĄZANIE 3: class Zesp { public: Zesp(); Zesp(float a, float b); friend void drukuj(Zesp z); private: float re, im; }; void main() { Zesp z(2, 5); drukuj(z); } Zesp::Zesp() { re = im = 0; } Zesp::Zesp(float a, float b) { re = a; im = b; } void drukuj(Zesp z) { cout << ‘(‘ << z.re << ‘,‘; cout << z.im << ‘)‘; } Funkcja zaprzyjaźniona ROZWIĄZANIE 4: void drukuj1(Zesp z) { cout << ‘(‘ << z.re << ‘,‘; cout << z.im << ‘)‘; } class Zesp { public: Zesp(); Zesp(float a, float b); void drukuj2(Zesp &z) friend void drukuj1(Zesp z); { friend void drukuj2(Zesp &z); cout << ‘(‘ << z.re << ‘,‘; friend void drukuj3(Zesp *z); cout << z.im << ‘)‘; } private: float re, im; }; void main() { Zesp z(2, 5); drukuj1(z); drukuj2(z); } void drukuj3(Zesp *z) { cout << ‘(‘ << z->re; cout << ‘,‘ << z->im << ‘)‘; } drukuj3(&z); Funkcja składowa a zaprzyjaźniona Zesp Zesp::dodaj(Zesp z) { Zesp wynik; Funkcja składowa klasy wynik.re = re + z.re; wynik.im = im + z.im; return wynik; } return Zesp(re + z.re, im + z.im); Zesp odejmij(Zesp z1, Zesp z2) { Zesp wynik; Funkcja zaprzyjaźniona wynik.re = z1.re – z2.re; z klasą wynik.im = z1.im - z2.im; return wynik; } return Zesp(z1.re - z2.re, z1.im - z2.im); Porównanie Funkcja składowa klasy deklaracja definicja wywołanie (aktywacja) Funkcja zaprzyjaźniona z klasą Zesp dodaj(Zesp z); friend Zesp odejmij(Zesp z1, Zesp z2); Zesp Zesp::dodaj(Zesp z) { Zesp wynik; wynik.re = re+z.re; wynik.im = im+z.im; return wynik; } Zesp odejmij(Zesp z1, Zesp z2) { Zesp wynik; wynik.re = z1.re - z2.re; wynik.im = z1.im – z2.im; return wynik; } Zesp z1, z2, z3; z3 = z1.dodaj(z2); Zesp z1, z2, z3; z3 = odejmij(z1, z2); Składowe statyczne Deklarowane są za pomocą słowa kluczowego static. Składowe statyczne: • pola statyczne • funkcje statyczne Pole statyczne klasy: • jest wspólne dla wszystkich obiektów tej klasy • jest widoczne we wszystkich obiektach tej klasy, ale w pamięci istnieje tylko jeden egzemplarz tego pola • istnieje niezależnie od tworzonych obiektów („zmienna globalna” dla klasy) • istnieje i można się do niego odwoływać nawet jeśli nie utworzono jeszcze żadnego obiektu klasy Dostęp do pól statycznych: • taki jak do zwykłych pól składowych • dodatkowo: poza klasą, podczas inicjalizacji pola • dodatkowo: za pomocą funkcji statycznych Inicjalizacja pól statycznych • pola statyczne inicjalizuje się poza klasą używając pełnej nazwy kwalifikowanej • pola statyczne nie mogą być inicjalizowane przez konstruktor (są wspólne dla wszystkich obiektów klasy, a nie dotyczą konkretnego obiektu - egzemplarza, instancji klasy) • prywatne pole statyczne poza klasą można tylko zainicjalizować (poza klasą nie ma do niego bezpośredniego dostępu poprzez jego nazwę) • publiczne pole statyczne poza klasą jest dostępne poprzez pełną nazwę kwalifikowaną Funkcje statyczne • funkcje statyczne służą do wykonywania operacji na polach statycznych • wewnątrz funkcji statycznej widoczne są tylko pola statyczne - nie są widoczne zwykłe, niestatyczne pola składowe - nie są widoczne niestatyczne funkcje składowe Składowe statyczne class Zesp { public: Zesp(); Zesp(float a, float b); ~Zesp(); static int Ile(); private: float re, im; static int licznik; }; void main() { cout << Zesp::Ile(); Zesp z1, z2(2, 3); cout << Zesp::Ile(); } int Zesp::licznik = 0; Zesp::Zesp() { re = im = 0; licznik++; } Zesp::Zesp(float a, float b) { re = a; im = b; licznik++; } Zesp::~Zesp() { licznik--; } int Zesp::Ile() { return licznik; }