LEKCJA 25: PRZYK�AD OBIEKTU. ________________________________________________________________ W trakcie tej lekcji dowiesz si�, jak praktycznie projektuje si� klasy i obiekty. Tw�j pierwszy obiekt zacznie dzia�a�. ________________________________________________________________ Nasz pierwszy, do�wiadczalny obiekt b�dzie zlicza� ile razy u�ytkownik nacisn�� okre�lony klawisz - np. liter� "A". Najpierw podejdziemy do problemu "klasycznie". Utworzymy struktur� Licznik, kt�r� mo�na wykorzysta� do przechowywania istotnych dla nas informacji: char znak - znak do zliczania int ile - ile razy wyst�pi� dany znak. Zwr�� uwag�, �e Licznik oznacza tu typ struktur (nowy formalny typ danych) a licznik oznacza nasz� robocz� zmienn� danego typu. struct Licznik //Licznik - nowy typ struktur { public: //Status public jest domy�lny dla struktur char znak; int ile; ... } licznik; //Zmienna typu "Licznik" Do p�l struktury licznik.znak i licznik.ile mo�emy odwo�ywa� si� w programie w nast�puj�cy spos�b: //Przypisanie (zainicjowanie pola struktury) licznik.znak = 'A'; cin >> licznik.znak; //Odczyt (wyprowadzenie) bie�. zawarto�ci pola struktury. cout << licznik.znak; Potrzebna nam b�dzie funkcja, przy pomocy kt�rej przeka�emy do struktury informacj�, jaki znak powinien by� zliczany. Nazwijmy t� funkcj� Inicjuj(). Funkcja Inicjuj() powinna nam zainicjowa� pole struktury tzn. po przekazaniu jej jako argumentu tego znaku, kt�ry ma podlega� zliczaniu, funkcja powinna "przenie��" znak i zapisa� go w polu licznik.znak naszej roboczej struktury. Wywo�anie funkcji w programie powinno wygl�da� tak: main() { .... Inicjuj('A'); .... //UWAGA: Nie tak: //licznik.Inicjuj() - funkcja jest zewn�trzna ! Aby funkcja inicjuj�ca pole struktury zadzia�a�a prawid�owo, jej definicja powinna wygl�da� tak: void Inicjuj(char x) //Deklaracja zmiennej znak. { licznik.znak = x; //x - wewn�trzna zmienna funkcji licznik.ile = 0; } Inicjuj�c struktur� licznik funkcja zeruje pole "ile" struktury. Przyda nam si� jeszcze jedna funkcja PlusJeden(). Ta funkcja powinna zwi�kszy� zmienn� s�u��c� do zliczania ile razy wyst�pi� interesuj�cy nas znak po ka�dym pojawieniu si� odpowiedniego znaku (w tym przypadku "A"). void PlusJeden(void) //Definicja funkcji { //incrementuj�cej licznik licznik.ile++; } Zbudowali�my licznik, kt�ry sk�ada si� z danych rozmieszczonych na polach struktury oraz dwu stowarzyszonych ze struktur� funkcji. Je�li spr�bujemy zastosowa� to w programie, gdzie: char znak_we - znak wczytany z klawiatury; program b�dzie wygl�da� tak: void main() { char znak_we; Inicjuj('A'); cout << "\nWpisz tekst zawierajacy litery A" cout << "\nK - oznacza Koniec zliczania: "; for(;;) //Wczytujemy znaki { cin >> znak_we; if (znak_we == 'k' || znak_we == 'K') break; if(znak_we == licznik.znak) PlusJeden(); } .... W tek�cie mog� wyst�pi� zar�wno du�e jak i ma�e litery. Je�li zechcemy zlicza� i jedne i drugie, mo�emy pos�u�y� si� funkcj� biblioteczn� C zamieniaj�c� ma�e litery na du�e - toupper(). Najpierw poddamy wczytany zank konwersji a nast�pnie por�wnamy z "zadanym" na polu licznik.znak: if(licznik.znak == toupper(znak_we)) PlusJeden(); Po przerwaniu p�tli przez u�ytkownika wystarczy sprawdzi� jaka warto�� jest wpisana w polu licznik.ile i mo�emy wydrukowa� wynik zliczania wyst�pie� litery 'A' we wprowadzonym tek�cie. cout << "\nLitera " << licznik.znak << " wyst�pila " << licznik.ile << " razy."; Program w ca�o�ci b�dzie wygl�da� tak: [P092.CPP] # include <iostream.h> # include <ctype.h> //Prototyp f. toupper() struct Licznik { char znak; int ile; } licznik; void Inicjuj(char x) { licznik.znak = x; licznik.ile = 0; } void PlusJeden(void) { licznik.ile++; } void main() { char znak_we; Inicjuj('A'); cout << "\nWpisz tekst zawierajacy litery A"; cout << "\nPierwzse wytapienie litery k lub K"; cout << "\n - oznacza Koniec zliczania: "; for(;;) { cin >> znak_we; if (znak_we == 'k' || znak_we == 'K') break; if(licznik.znak == toupper(znak_we)) PlusJeden(); } cout << "\nLitera " << licznik.znak << " wystapila " << licznik.ile << " razy."; } Je�li dane i funkcje po��czymy w jedn� ca�o�� - powstanie obiekt. Zawarto�� naszego obiektu powinna wygl�da� tak: Dane: char znak; int ile; Funkcje: void Inicjuj(char); void PlusJeden(void); ��czymy w ca�o�� funkcje operuj�ce pewnymi danymi i te w�a�nnie dane. Co wi�cej, je�li zaistniej� takie funkcje, kt�re nie b�d� wykorzystywane przez nikogo wi�cej poza w�asnym obiektem i poza jego sk�adnikami: funkcj� Inicjuj() i funkcj� PlusJeden(), funkcje te nie musz� by� widoczne, ani dost�pne dla reszty programu. Takie funkcje mog� wraz z danymi zosta� uznane za prywatn� cz�� obiektu. Takie praktyki, szczeg�lnie w programach przeznaczonych dla �rodowiska Windows s� uzasadnione i po�yteczne. Rozwa�my obiekt, modularyzacj� i hermetyzacj� obiektu na konkretnych przyk�adach. Zacznijmy od zdefiniowania klasy. class Licznik { char znak; int ile; public: void Inicjuj(char); void PlusJeden(void); }; Nast�pny krok, to zdefiniowanie obu funkcji. Zwr�� uwag�, �e funkcje nie s� ju� definiowane "niezale�nie", lecz w stosunku do w�asnej klasy: void Licznik::Inicjuj(char x) { znak = x; ile = 0; } void Licznik::PlusJeden(void) { ile++; } Skoro funkcje widz� ju� wy��cznie w�asn� klas�, zapis licznik.znak mo�e zosta� uproszczony do --> znak i licznik.ile do --> ile Aby wskaza�, �e funkcje s� cz�onkami klasy Licznik stosujemy operator :: (oper. widoczno�ci/przes�aniania - ang. scope resolution operator). Taki spos�b zapisu definicji funkcji oznacza dla C++, �e funkcja jest cz�onkiem klasy (ang. member function). Logika C++ w tym przypadku wygl�da tak: * Prototypy funkcji nale�y umie�ci� w definicji klasy. * Definicje funkcji mog� znajdowa� si� w dowolnym miejscu programu, poniewa� operator przes�aniania :: pozwala rozpatrywa� klas� podobnie jak zmienne globalne. * Wstawiaj�c operator :: pomi�dzy nazw� klasy i prototyp funkcji informujemy C++ �e dana funkcja jest cz�onkiem okre�lonej klasy. Funkcje - cz�onkowie klas nazywane s� cz�sto METODAMI. Definicje klas i definicje funkcji - METOD s� cz�sto umieszczane razem - w plikach nag��wkowych. Je�li pos�ugujemy si� tak� metod�, wystarczy do��czy� odpowiedni plik dyrektyw� # include. Kompilator C++ skompiluje wtedy automatycznie wszystkie funkcje, kt�re znajdzie w do��czonych plikach nag��wkowych. Mo�emy przyst�pi� do utworzenia programu. main() { char znak_we; //Dekl. zwyklej zmiennej Licznik licznik; //Deklarujemy obiekt klasy Licznik licznik.Inicjuj('A'); //Inicjujemy licznik ... Mo�emy teraz okre�li� ilo�� wprowadzonych z klawiatury liter 'A' oraz 'a' i wyprowadzi� j� na ekran monitora. Pojawia si� jednak pewien problem. Nie uda si� si�gn�� z zewn�trz do prywatnych danych obiektu tak, jak poprzednio: if(licznik.znak == toupper(znak_we)) .... Potrzebna nam b�dzuie jeszcze jedna metoda autoryzowana do dost�pu do danych obiektu: char Licznik::Pokaz(void); kt�ra nie b�dzie w momencie wywo�ania pobiera� od programu �adnych argument�w (void), natomiast pobierze znak z pola char Licznik.znak i przeka�e t� informacj� w postaci zmiennej typu char do programu. Definicja takiej metody powinna by� nast�puj�ca: char Licznik::Pokaz(void) { return znak; } Ten sam problem wyst�pi przy pr�bie pobrania od obiektu efekt�w jego pracy - stanu pola licznik.ile. Do tego te� niezb�dna jest autoryzowana do dost�pu metoda. Nazwiemy j� Efekt(): int Licznik::Efekt(void) { return ile; } Program w wersji obiektowej b�dzie wygl�da� tak: [P093.CPP] # include <ctype.h> # include <iostream.h> class Licznik { char znak; int ile; public: void Inicjuj(char); void PlusJeden(void); char Pokaz(void); int Efekt(void); }; void main() { char znak_we; Licznik licznik; licznik.Inicjuj('A'); cout << "\nWpisz tekst zawierajacy litery A"; cout << "\nPierwsze wytapienie litery k lub K"; cout << "\n - oznacza Koniec zliczania: "; for(;;) { cin >> znak_we; if (znak_we == 'k' || znak_we == 'K') break; if(licznik.Pokaz() == toupper(znak_we)) licznik.PlusJeden(); } cout << "\nLitera " << licznik.Pokaz() << " wystapila " << licznik.Efekt() << " razy."; } /* Definicje wszystkich funkcji: */ void Licznik::Inicjuj(char x) { znak = x; ile = 0; } void Licznik::PlusJeden(void) { ile++; } char Licznik::Pokaz(void) { return znak; } int Liczni...
ZAZZY