LEKCJA26.TXT

(20 KB) Pobierz
LEKCJA 26: CO TO JEST KONSTRUKTOR. 
________________________________________________________________ 
W trakcie tej lekcji dowiesz si�, w jaki spos�b w pami�ci  
komputera s� tworzone obiekty.  
________________________________________________________________ 
 
 
C++ zawiera specjaln� kategori� funkcji - konstruktory w celu  
automatyzacji inicjowania struktur (i obiekt�w). Konstruktory to 
specjalne funkcje b�d�ce cz�onkami struktur (kategorii member  
functions) kt�re s� automatycznie wywo�ywane i dokonuj�  
zainicjowania struktury zgodnie z naszymi �yczeniami, po  
napotkaniu w programie pierwszej deklaracji struktury/obiektu  
danego typu.  
 
PRZYK�ADOWY KONSTRUKTOR.  
 
Struktura Licznik zawiera funkcj� inicjuj�c� obiekt (niech  
obiekt b�dzie na razie zmienn� typu struktura):  
  
struct Licznik               //Typ formalny struktur 
{    
  char znak;   
  int ile;   
} licznik;                   //Przykladowa struktura 
  
void Inicjuj(char x)         //Funkcja inicjuj�ca 
{   
  licznik.znak = x;   
  licznik.ile = 0;   
}   
 
Zdefiniujmy nasz� struktur� w spos�b bardziej  
"klasowo-obiektowy":  
 
struct Licznik 
{  
private: 
  char znak;  
  int ile;  
public: 
   void Inicjuj(char);  
   void PlusJeden(void);  
};  
 
Funkcja Inicjuj() wykonuje takie dzia�anie jakie mo�e wykona�  
konstruktor struktury (obiektu), z t� jednak r�nic�, �e  
konstruktor jest wywo�ywany automatycznie. Je�li wyposa�ymy  
struktur� Licznik w konstruktor, to funkcja Inicjuj() oka�e si�  
zb�dna. Aby funkcja Inicjuj() sta�a si� konstruktorem, musimy  
zmieni� jej nazw� na nazw� typu struktury, do kt�rej konstruktor 
 
ma nale�e�. Zwr�� uwag�, �e konstruktor, w przeciwie�stwie do  
innych, "zwyk�ych" funkcji nie ma podanego typu warto�ci  
zwracanej: 
 
struct Licznik 
{  
private: 
  char znak;  
  int ile;  
public: 
   Licznik(void);       //Konstruktor nie pobiera argumentu 
   void PlusJeden(void);  
};  
 
Teraz powinni�my zdefiniowa� konstruktor. Zrobimy to tak, jak  
wcze�niej definiowali�my funkcj� Inicjuj().  
  
Licznik::Licznik(void)   //Konstruktor nie pobiera argumentu 
{   
  ile = 0;   
}   
 
Je�li formalny typ struktur (klasa) posiada kostruktor, to po  
rozpocz�ciu programu i napotkaniu deklaracji struktur danego  
typu konstruktor zostanie wywo�any automatycznie. Dzi�ki temu  
nie musimy "r�cznie" inicjowa� struktur na pocz�tku programu.  
Jednak�e nasz przyk�adowy konstruktor nie za�atwia wszystkich  
problem�w - nie ustawia w strukturze zmiennej (pola) int znak -  
okre�laj�cego, kt�ry znak powinien by� zliczany w liczniku. W  
tak zainicjowanej strukturze zmienna ile jest zerowana, ale  
zawarto�� pola znak pozostaje przypadkowa. Niby wszystko w  
porz�dku, ale wygl�da to niesolidnie. Czy nie mo�naby przekaza�  
parametru przy pomocy konstruktora? Mo�na! Konstruktor  
"bezparametrowy"  
 
Licznik::Licznik(void)    
 
taki, jak powy�ej to tylko szczeg�lny przypadek - tzw.  
konstruktor domy�lny (ang. default constructor).  
 
PRZEKAZYWANIE ARGUMENT�W DO KOSTRUKTORA.  
 
Czasem chcemy zainicjowa� now� struktur� ju� z pewnymi  
ustawionymi parametrami. Te pocz�tkowe parametry struktury  
mo�emy przekaza� jako argumenty konstruktora. 
 
struct Licznik 
{  
private: 
  char znak;  
  int ile;  
public: 
   Licznik(char);         //Konstruktor z argumentem typu char 
   void PlusJeden(void);  
};  
 
  
Licznik::Licznik(char x)   //Konstruktor z jednym argumentem 
{   
 ... 
}   
 
main()  
{  
  Licznik licznik('A');     //Deklaracja struktury typu Licznik  
// oznacza to automatyczne wywo�anie konstruktora z argumentem 
.... 
  
Poniew� nowy konstruktor pobiera od programu argument typu  
znakowego char, wi�c i definicj� konstruktora nale�y zmieni�: 
 
Licznik::Licznik(char x) //Konstruktor z jednym argumentem 
{   
  ile = 0;   
  znak = x; 
}   
 
Je�li parametr�w jest wi�cej ni� jeden, mo�emy je przekaza� do  
konstruktora, a konstruktor wykorzysta je do zainicjowania  
struktury w nast�puj�cy spos�b:  
 
struct Sasiedzi                  //s�siedzi 
{  
private: 
    char Tab_imion[4];  
 ... 
public:  
    Sasiedzi(char *s1, char *s2, char *s3, char s4);   
 ...  
};  
 
main()  
{  
  Sasiedzi chopy("Helmut", "Ulrich", "Adolf", "Walter");  
....  
 
Przekazanie konstruktorowi argument�w i w efekcie automatyczne  
ustawiamie przez konstruktor paramatr�w struktury ju� w momencie 
 
zadeklarowania struktury w programie rozwi�zuje wiele problem�w. 
 
W C++ istnieje jednak�e pewne do�� istotne ograniczenie - nie  
mo�emy zadeklarowa� tablicy z�o�onej z obiekt�w posiadaj�cych  
konstruktory, chyba �e wszystkie konstruktory s� bezparametrowe  
(typu default constructors).  
 
Udoskonalmy teraz nasz program zliczaj�cy wyst�pienia w tek�cie  
litery a pos�uguj�c si� konstruktorem struktury.  
 
[P094.CPP]        /* Wersja ze struktur� */ 
  
# include <ctype.h>   
# include <iostream.h>   
   
struct Licznik   
{    
private:  
  char znak;    
  int ile;    
public:   
   Licznik(char);                //Konstruktor  
   void PlusJeden(void);    
   char Pokaz(void);    
   int Efekt(void);   
};    
   
Licznik::Licznik(char x)            //Def. konstruktora  
{    
  znak = x;    
  ile = 0;    
}    
  
void main()    
{    
  Licznik  licznik('A');      //Zainicjowanie przez konstruktor  
  
  cout << "Sprawdzamy: znak    ile? " << "\n\t\t"   
       <<  licznik.Pokaz() << "\t";   
  cout <<  licznik.Efekt();  
  
  cout << "\nWpisz tekst zawierajacy litery A";   
  cout << "\nPierwsze wytapienie litery k lub K";    
  cout << "\n - oznacza Koniec zliczania: ";     
  for(;;)      
    {    
      char znak_we;  
      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 pozosta�ych funkcji:                          */   
  
void Licznik::PlusJeden(void) { ile++; }  
char Licznik::Pokaz(void) { return (znak); }  
int Licznik::Efekt(void) { return (ile); }  
   
Po zamianie s�owa kluczowego struct na class (licznik ze  
struktury stanie si� obiektem, a Licznik - z formalnego typu  
struktur - klas�) wystarczy w programie zlikwidowa� zb�dne s�owo 
 
"private" i wersja obiektowa programu jest gotowa do pracy.  
 
[P095.CPP]        /* Wersja z klas� i obiektem */ 
  
# include <ctype.h>   
# include <iostream.h>   
   
class Licznik   
{    
  char znak;    
  int ile;    
public:   
   Licznik(char);                //Konstruktor  
   void PlusJeden(void);    
   char Pokaz(void);    
   int Efekt(void);   
};    
   
Licznik::Licznik(char x) //Def. konstruktora  
{    
  znak = x;    
  ile = 0;    
}    
  
void main()    
{    
  Licznik  licznik('A');      //Zainicjowanie obiektu licznik 
  
  cout << "Sprawdzamy:  znak    ile? " << "\n\t\t"   
       <<  licznik.Pokaz() << "\t";   
  cout <<  licznik.Efekt();  
  
  cout << "\nWpisz tekst zawierajacy litery A";   
  cout << "\nPierwsze wytapienie litery k lub K";    
  cout << "\n - oznacza Koniec zliczania: ";     
  for(;;)      
    {    
      char znak_we;  
      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.";     
}    
    
void Licznik::PlusJeden(void) { ile++; }  
char Licznik::Pokaz(void) { return znak; }  
int Licznik::Efekt(void) { return ile; }  
   
Pora w tym miejscu zaznaczy�, �e C++ oferuje nam jeszcze jedno  
specjalne narz�dzie podobnej kategorii. Podobnie, jak do  
tworzenia (struktur) obiekt�w mo�emy zastosowa� konstruktor, tak 
 
do skasowania obiektu mo�emy zastosowa� tzw. desruktor (ang.  
destructor). Nazwy konstruktora i destruktora s� identyczne z  
nazw� macie�ystego typu struktur (macie�ystej klasy), z tym, �e  
nazwa destruktora poprzedzona jest znakiem "~" (tylda). 
 
CO TO JEST DESTRUKTOR.  
 
Specjalna funkcja - destruktor (je�li zadeklarujemy zastosowanie 
 
takiej funkcji) jest wywo�ywana automatycznie, gdy program  
zako�czy korzystanie z obiektu. Konstruktor tworzy, a destruktor 
 
(jak sama nazwa wskazuje) niszczy struktur� (obiekt) i zwalnia  
przyporz�dkowan� pami��. Przyk�ad poni�ej to program  
manipuluj�cy stosem, rozbudowany tak, by zawiera� i konstruktor  
i destruktor struktury (obiektu). Zorganizujmy zarz�dzanie  
pami�ci� przeznaczon� dla stosu w taki spos�b:  
 
struct Stos  
{  
private: 
  int *bufor_danych;   
  int licznik;   
public:  
     Stos(int ile_RAM);                  /* Konstruktor 
     int Pop(int *ze_stosu);  
     int Push(int na_stos);  
};  
 
gdzie:  
*bufor_danych - wska�nik do bufora (wype�niaj�cego rol� stosu),  
licznik - wierzcho�ek stosu, je�li == -1, stos jest pusty. 
Stos::Stos(...) - konstruktor inicjuj�cy struktur� typu Stos  
(lub obiekt klasy Stos),  
ile_RAM - ilo�� pami�ci potrzebna do poprawnego dzia�anie stosu, 
*ze_stosu - wska�nik do zmiennej, kt�rej nale�y przypisa�  
warto�� zdj�t� w�a�nie ze stosu, 
na_stos - liczba przeznaczona do zapisu na stos. 
 
Zajmijmy si� teraz definicj� konstruktora. Wywo�uj�c konstruktor 
 
w programie (deklaruj�c u�ycie w programie struktury typu Stos)  
przeka�emy mu jako argument ilo�� potrzebnej nam pami�ci RAM w  
bajtach. Do przy...
Zgłoś jeśli naruszono regulamin