r19-06.doc

45
 Rozdział 19. WzorceSzablonyWzorc e Przydatny m dla programistów C++ nowym narzędziem są „typy sparametry zowane”, czyli wzorcewzorce. WzorceSą one tak !ytecznym narzędziem, !e do de"inic#i #ęzyka C++ zosta$a wprowadzona standardowa %i%lioteka wzorców &S'(, Standard 'emplate (i%rary). * tego rozdzia$ dowiesz się czym są wzorcewzorce i #ak ic !ywa-,  #ak tworzy- wzorcewzorce klas,  #ak tworzy- wzorcewzorce "nkc#i, czym #est standardowa %i%lioteka wzorcówwzorców i #ak z nie# korzysta-. Czym są wzorcewzorce? Pod koniec czternastego rozdzia$ stworzylimy o%iekt PartsList i wykorzystalimy go do stworzenia katalog częci, klasy PartsCatalog. /eli #ednak ccieli%ymy na o%iekcie PartsList oprze- listę kotów, po#awi$%y się pro%lem klasa PartsList wie tylko o częciac. 0%y rozwiąza- ten pro%lem, mogli%ymy stworzy- klasę %azową List. Wtedy mogli%ymy wycią- i wklei- większo- kod z klasy PartsList do nowe# deklarac#i klasy CatsList. 'y dzie1 pó2nie#, gdy%ymy zeccieli stworzy - listę o%iektów Car, msieli%ymy stworzy- nową klasę i znów kopiowa- i wkle#a- kod.  3ie #est to do%re ro związanie. * czase m mog$o%y się okaza- , !e klasa List oraz klasy z nie# wyprowadzone mszą %y- rozszerzone. 4ozprowadzenie wszystkic zmian po wszystkic  powiązanyc z nią klas ac %y$o%y koszmare m. Pro%lem ten rozwiąz#ą wzorce, które po zaadoptowani standard 03S5 sta$y się integralną częcią #ęzyka. Podo%nie #ak wszystkie elementy w C++, są one %ardzo elastyczne, a przy tym  %ezpieczne &pod względem typów).

Upload: greg

Post on 05-Nov-2015

213 views

Category:

Documents


0 download

TRANSCRIPT

Szablon dla tlumaczy

2

Cz I ( Podstawy obsugi systemu WhizBang (Nagwek strony)

Rozdzia 19.Wzorce

Przydatnym dla programistw C++ nowym narzdziem s typy sparametryzowane, czyli wzorce. S one tak uytecznym narzdziem, e do definicji jzyka C++ zostaa wprowadzona standardowa biblioteka wzorcw (STL, Standard Template Library).

Z tego rozdziau dowiesz si:

czym s wzorce i jak ich uywa,

jak tworzy wzorce klas,

jak tworzy wzorce funkcji,

czym jest standardowa biblioteka wzorcw i jak z niej korzysta.

Czym s wzorce?

Pod koniec czternastego rozdziau stworzylimy obiekt PartsList i wykorzystalimy go do stworzenia katalogu czci, klasy PartsCatalog. Jeli jednak chcielibymy na obiekcie PartsList oprze list kotw, pojawiby si problem: klasa PartsList wie tylko o czciach.

Aby rozwiza ten problem, moglibymy stworzy klas bazow List. Wtedy moglibymy wyci i wklei wikszo kodu z klasy PartsList do nowej deklaracji klasy CatsList. Tydzie pniej, gdybymy zechcieli stworzy list obiektw Car, musielibymy stworzy now klas i znw kopiowa i wkleja kod.

Nie jest to dobre rozwizanie. Z czasem mogoby si okaza, e klasa List oraz klasy z niej wyprowadzone musz by rozszerzone. Rozprowadzenie wszystkich zmian po wszystkich powizanych z ni klasach byoby koszmarem.

Problem ten rozwizuj wzorce, ktre po zaadoptowaniu standardu ANSI stay si integraln czci jzyka. Podobnie jak wszystkie elementy w C++, s one bardzo elastyczne, a przy tym bezpieczne (pod wzgldem typw).

Typy parametryzowane

Wzorce pozwalaj na nauczenie kompilatora, w jaki sposb ma tworzy list rzeczy dowolnego typu (zamiast tworzenia zestawu list specyficznego typu) PartsList jest list czci, CatsList jest list kotw. Listy te rni si tylko rodzajem przechowywanych w nich rzeczy. W trakcie korzystania z wzorcw typ rzeczy zawartej w licie staje si parametrem definicji klasy.

Standardowym komponentem w prawie wszystkich bibliotekach C++ jest klasa tablicy. Jak widzielimy w przypadku klasy List, tworzenie osobnych tablic dla liczb cakowitych, liczb zmiennoprzecinkowych czy dla obiektw jest mudne i nieefektywne. Wzorce umoliwiaj zadeklarowanie sparametryzowanej klasy tablicy, a nastpnie okrelenie, jaki typ obiektu bdzie zawiera kady jej egzemplarz. Zauwa, e standardowa biblioteka wzorcw zawiera standardowy zestaw klas kontenerw, obejmujcy tablice, listy i tak dalej. W tym rozdziale sami stworzymy klas kontenera, aby przekona si, jak dziaaj wzorce, ale w komercyjnych aplikacjach prawie z pewnoci uyjesz klas standardowych (zamiast tworzy wasne).

Tworzenie egzemplarza wzorca

Tworzenie egzemplarza wzorca znacza tworzenie okrelonego typu na podstawie tego wzorca. Poszczeglne, tworzone aktualnie klasy s nazywane egzemplarzami wzorca.

Parametryzowane wzorce pozwalaj na tworzenie klasy oglnej i przekazywanie jej typw jako parametrw, w celu stworzenia konkretnego egzemplarza wzorca.

Definicja wzorca

Parametryzowany obiekt Array (wzorzec dla tablic) deklarujemy, piszc:

1: template // deklaruje wzorzec i parametr

2: class Array // parametryzowana klasa

3: {

4: public:

5: Array();

6: // w tym miejscu pena deklaracja klasy

7: };

Sowo kluczowe template (wzorzec) jest uywane na pocztku kadej deklaracji i definicji klasy wzorcowej. Parametry wzorca wystpuj po sowie kluczowym template. Parametry s zmieniane (uaktualniane) w kadym egzemplarzu. Na przykad, w pokazanym tu wzorcu tablicy zmienia si typ przechowywanych w niej obiektw. Jeden egzemplarz moe by tablic liczb cakowitych, a inny moe by tablic obiektw typu Animal.

W tym przykadzie zostao uyte sowo kluczowe class, po ktrym nastpuje identyfikator T. Sowo kluczowe class wskazuje e ten parametr (identyfikator) jest typem. Identyfikator T jest uywany w pozostaej czci definicji wzorca i odnosi si do typu parametryzowanego. W jednym z egzemplarzy tej klasy w miejscu wszystkich identyfikatorw T zostanie podstawiony na przykad typ int, a w innym egzemplarzu zostanie podstawiony typ Cat.

Aby zadeklarowa egzemplarze wzorca typu int i Cat parametryzowanej klasy Array, moglibymy napisa:

Array anIntArray;

Array aCatArray;

Obiekt anIntArray to obiekt typu tablica liczb cakowitych; obiekt aCatArray to obiekt typu tablica kotw. Od tego momentu moemy uywa typu Array wszdzie tam, gdzie normalnie uywalibymy jakiego typu (np. dla wartoci zwracanej przez funkcj, jako parametru funkcji i tak dalej). Pen deklaracj tej okrojonej klasy Array przedstawia listing 19.1.

UWAGAListing 19.1 nie jest kompletnym programem!

Listing 19.1. Wzorzec klasy tablicy

0: //Listing 19.1 Wzorzec klasy tablicy

1: #include

2: using namespace std;

3: const int DefaultSize = 10;

4:

5: template // deklaruje wzorzec i parametr

6: class Array // parametryzowana klasa

7: {

8: public:

9: // konstruktory

10: Array(int itsSize = DefaultSize);

11: Array(const Array &rhs);

12: ~Array() { delete [] pType; }

13:

14: // operatory

15: Array& operator=(const Array&);

16: T& operator[](int offSet) { return pType[offSet]; }

17:

18: // akcesory

19: int getSize() { return itsSize; }

20:

21: private:

22: T *pType;

23: int itsSize;

24: };

Wynik

Brak. Program nie jest kompletny.

Analiza

Definicja wzorca rozpoczyna si w linii 5. od sowa kluczowego template, po ktrym wystpuje parametr. W tym przypadku parametr jest identyfikowany przez sowo kluczowe class, za do reprezentowania parametryzowanego typu zosta uyty identyfikator T.

Od linii 6. a do koca wzorca w linii 24., pozostaa cz deklaracji wyglda tak samo jak deklaracja kadej innej klasy. Jedyn rnic jest to, e tam, gdzie normalnie wystpowaby typ obiektu, wystpuje identyfikator T. Na przykad, mona oczekiwa, e operator[] bdzie zwraca referencj do obiektu zawartego w tablicy rzeczywicie, jest zadeklarowany jako zwracajcy referencj do T.

Gdy deklarowany jest egzemplarz tablicy liczb cakowitych, to zdefiniowany dla tej tablicy operator= zwrci referencj do liczby cakowitej. Gdy jest deklarowany egzemplarz tablicy obiektw klasy Animal, to zdefiniowany dla tej tablicy operator= zwrci referencj do obiektu Animal.

Uycie nazwy

Sowo Array moe by uyte bez kwalifikowania wewntrz deklaracji klasy. We wszystkich innych miejscach programu do klasy tej trzeba si odwoywa jako do Array. Na przykad, jeli nie wpiszemy konstruktora wewntrz deklaracji klasy, to musimy napisa:

template

Array::Array(int size):

itsSize = size

{

pType = new T[size];

for (int i = 0; i < size; i++)

pType[i] = 0;

}

Deklaracja w pierwszej linii tego fragmentu kodu jest wymagana do zidentyfikowania typu (class T). Nazw wzorca jest Array, a nazw funkcji jest Array(int size). Pozostaa cz funkcji jest taka sama, jak w przypadku zwykej funkcji. Powszechn i zalecan praktyk jest przetestowanie dziaania klasy i jej funkcji jako zwykych deklaracji przed zamienieniem ich we wzorzec. To rozwizanie upraszcza tworzenie wzorca, umoliwiajc skoncentrowanie si na celu programowania; rozwizanie, poprzez stworzenie wzorca, uoglniamy dopiero pniej.

Implementowanie wzorca

Pena implementacja klasy wzorca Array wymaga zaimplementowania konstruktora kopiujcego, operatora= i tak dalej. Prosty program sterujcy, przenaczony do testowania tej klasy wzorcowej przedstawia listing 19.2.

UWAGANiektre starsze kompilatory nie obsuguj wzorcw. Wzorce s jednak czci standardu ANSI C++ i s obsugiwane w obecnych wersjach kompilatorw wiodcych producentw. Jeli masz bardzo stary kompilator, nie bdziesz mg skompilowa i uruchomi przykadowych programw przedstawionych w tym rozdziale. Jednak mimo to, powiniene go w caoci i wrci do niego pniej, gdy zdobdziesz nowszy kompilator.

Listing 19.2. Implementacja wzorca klasy tablicy

0: //Listing 19.2 Implementacja wzorca klasy tablicy

1: #include

2:

3: const int DefaultSize = 10;

4:

5: // deklaruje prost klas Animal tak, abymy

6: // mogli tworzy tablice obiektw typu Animal

7:

8: class Animal

9: {

10: public:

11: Animal(int);

12: Animal();

13: ~Animal() {}

14: int GetWeight() const { return itsWeight; }

15: void Display() const { std::cout