LEKCJA25.TXT

(9 KB) Pobierz
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...
Zgłoś jeśli naruszono regulamin