LEKCJA 33: WSKAŹNIKI DO OBIEKTÓW. ________________________________________________________________ W trakcie tej lekcji dowiesz się, jak posługiwać się obiektami za pośrednictwem wskaźników. ________________________________________________________________ Wskaźniki do obiektów funkcjonują podobnie jak wskaźniki do struktur. Operator -> pozwala na dostęp zarówno do danych jak i do funkcji. Dla przykładu wykorzystamy obiekt naszej prywatnej klasy Licznik. class Licznik { public: char moja_litera; int ile; Licznik(char znak) { moja_litera = z; ile = 0; } void Skok_licznika(void) { ile++; } }; Aby w programie można było odwołać się do obiektu nie poprzez nazwę a przy pomocy wskaźnika, zadeklarujemy wskaźnik do obiektów klasy Licznik: Licznik *p; Wskaźnik w programie możemy zastosować np. tak: p->Skok_licznika(); (czytaj: Wywołaj metodę "Skok_licznika()" w stosunku do obiektu wskazywanego w danym momencie przez wskaźnik p) Trzeba pamiętać, że sama deklaracja w przypadku referencji i wskaźników nie wystarcza. Przed użyciem należy jeszcze zainicjować wskaźnik w taki sposób, by wskazywał na nasz obiekt-licznik. Wskaźnik do obiektu inicjujemy w taki sam sposób jak każdy inny pointer: p = &Obiekt; Możemy przystąpić do utworzenia programu przykładowego. [P119.CPP] # include "ctype.h" # include "iostream.h" class Licznik { public: char moja_litera; int ile; Licznik(char z) { moja_litera = z; ile = 0; } void Skok_licznika(void) { ile++; } }; void main() { char znak; cout << "\nPodaj litere do zliczania: "; cin >> znak; Licznik Obiekt1(znak), Obiekt2('a'), *p1, *p2; p1 = &Obiekt1; p2 = &Obiekt2; cout << "\n Wpisz ciag znakow"; cout << "zakonczony kropka [.] i [Enter] \n"; for(;;) { cin >> znak; if(znak == '.') break; if(znak == p1->moja_litera) p1->Skok_licznika(); if(znak == p2->moja_litera) p2->Skok_licznika(); } cout << "\nBylo " << p1->ile; cout << " liter: " << p1->moja_litera; p1 = p2; cout << "\nBylo " << p1->ile; cout << " liter: " << p1->moja_litera; } Możemy oczywiście np. stosować przypisanie, inkrementować i dekrementować pointer oraz realizować arytmetykę na wskaźnikach dokładnie tak samo, jak w przypadku innych zmiennych. this - WSKAŹNIK SPECJALNY. Poświęcimy teraz chwilę uwagi pewnemu specjalnemu wskaźnikowi. Specjalnemu (i ważnemu) na tyle, że aż "dorobił się" w C++ własnego słowa kluczowego "this". Każdej funkcji - metodzie zadeklarowanej wewnątrz klasy zostaje w momencie wywołania w niejawny sposób (ang. implicitly) przekazany wskaźnik do obiektu (w stosunku do którego funkcja ma zadziałać). Pointer wskazuje funkcji w pamięci ten obiekt, którego członkiem jest dana funkcja. Bez istnienia takiego właśnie wskaźnika nie moglibyśmy stosować spokojnie funkcji, nie moglibyśmy odwoływać się do pola obiektu, gdybyśmy nie wiedzieli jednoznacznie, o który obiekt chodzi. Program posługuje się automatycznie niejawnym wskaźnikiem do obiektu (ang. implicit pointer). Możemy wykorzystać ten istniejący, choć do tej pory nie widoczny dla nas pointer posługując się słowem kluczowym this (ten). This pointer wskazuje na obiekt, do którego należy funkcja. Korzystając z tego wskaźnika funkcja może bez cienia wątpliwości zidentyfikować właśnie ten obiekt, z którym pracuje a nie obiekt przypadkowy. [!!!] FUNKCJE KATEGORII static NIE OTRZYMUJĄ POINTERA this. Należy pamiętać, że wskaźnik this istnieje wyłącznie podczas wykonywania metod (ang. class member function execution), za wyjątkiem funkcji statycznych. Jeśli w programie zadeklarujemy klasę Klasa: class Klasa { int dane; ... } a wewnątrz tej klasy metodę Pokazuj(): class Klasa { int dane; public: void Pokazuj(); ... } void Klasa::Pokazuj(void) { cout << dane; } To zdefiniowanie funkcji Pokazuj() z zastosowaniem pointera this i notacji wskaźnikowej (p->), jak poniżej, będzie równoważne: void Klasa::Pokazuj(void) { cout << this->dane; } Przypomnijmy, że taka notacja wskaźnikowa oznacza: "Wyprowadź zawartość pola "dane" obiektu, na który wskazuje wskaźnik" (ponieważ jest to wskaźnik this, więc chodzi o własny obiekt).