Programowanie obiektowe Wykład 5. C++: szablony
Szablony Szablony to technika realizacji polimorfizmu na innym poziomie niż za pomocą funkcji wirtualnych i dziedziczenia. Mechanizm ten można rozumieć jako inteligentniejsze makrodefinicje. Szablony nie są w bezpośredni sposób związane z programowaniem obiektowym.
Szablony funkcji przykład problemu: definiujemy funkcję porównującą......liczby całkowite: int compare(int a, int b) if(a<b)return1;elseif(b<a) return-1;elsereturn0;
Szablony funkcji przykład problemu: definiujemy funkcję porównującą......liczby całkowite: int compare(int a, int b) if(a<b)return1;elseif(b<a) return-1;elsereturn0;...liczby rzeczywiste: int compare(float a, float b) if(a<b)return1;elseif(b<a) return-1;elsereturn0;
Szablony funkcji przykład problemu: definiujemy funkcję porównującą......liczby całkowite: int compare(int a, int b) if(a<b)return1;elseif(b<a) return-1;elsereturn0;...liczby rzeczywiste: int compare(float a, float b) if(a<b)return1;elseif(b<a) return-1;elsereturn0;...itaksamodlakażdegoinnegotypu
Szablony funkcji przykład problemu: definiujemy funkcję porównującą......liczby całkowite: int compare(int a, int b) if(a<b)return1;elseif(b<a) return-1;elsereturn0;...liczby rzeczywiste: int compare(float a, float b) if(a<b)return1;elseif(b<a) return-1;elsereturn0;...itaksamodlakażdegoinnegotypu... pod warunkiem, że ma zdefiniowany operator <
Szablony funkcji przykład problemu: definiujemy funkcję porównującą......liczby całkowite: int compare(int a, int b) if(a<b)return1;elseif(b<a) return-1;elsereturn0;...liczby rzeczywiste: int compare(float a, float b) if(a<b)return1;elseif(b<a) return-1;elsereturn0;...pudełka class Pudelko public: float dl,sz,wy; Pudelko(float d,floats,floatw):dl(d),sz(s),wy(w) int operator<(pudelko& p) return dl*sz*wy < p.dl*p.sz*p.wy; ; int compare(pudelko a, Pudelko b) if(a<b)return1;elseif(b<a) return-1;elsereturn0;
Szablony funkcji podstawowe informacje szablon funkcji jest sparametryzowaną definicją funkcji szablon funkcji definiuje się w zakresie globalnym parametrem szablonu funkcji jest typ(klasa), bądź lista typów wszystkie parametry szablonu muszą wystąpić w opisie argumentów funkcji szablonowej(kompilator odnajduje szablon na podstawie wywołania funkcji) Składnia: template< opis parametrów > definicja funkcji
Szablony funkcji przykład class Pudelko public: float dl,sz,wy; Pudelko(float d,floats,floatw):dl(d),sz(s),wy(w) int operator<(pudelko& p) return dl*sz*wy < p.dl*p.sz*p.wy; ; template <class T> intcompare(t a,tb) if(a<b) return-1; else if(b<a) return 1; else return 0; intmain() cout << compare(1,2) << endl //-1 << compare(1.5,2.5) << endl //-1 <<compare( a, b ) <<endl //-1 << compare(pudelko(1.0,2.0,2.0),pudelko(2.0,1.5,4.2)) << endl;//-1
Szablony funkcji parametry parametrem szablonu funkcji jest typ(klasa), bądź lista typów wszystkie parametry szablonu muszą wystąpić w opisie argumentów funkcji szablonowej(kompilator odnajduje szablon na podstawie wywołania funkcji) oprócz obowiązkowego użycia parametrów szablonu w opisie argumentów funkcji szablonowej, można ich używać w dowolnym miejscu w definicji tej funkcji(jako nazwy typu). template<class S, class T> T* jakasfunkcja(s a, T b) T*l=new(T); int r=sizeof(s);... return l;
Szablony funkcji jedynym ograniczeniem, jakie w definicji szablonu można nałożyć na typy argumetów funkcji szablonowej jest by niektóre z nich były takie same, np. szablon template<class K,class L,class M> voidf(ka,lb,kc,md)... pasuje do wywołania f(3, e,5,"ala") ale do wywołania nie. f(3, e, a,"ala")
Szablony funkcji jak to działa natrafiając na wywołanie funkcji, kompilator sprawdza, czy istnieje funkcja o podanej nazwie, liczbie i typie argumentów jeśli nie, sprawdza, czy istnieje szablon pozwalający taką funkcję wygenerować, jeśli tak generuje odpowiednią funkcję jeśli nie, sprawdza czy isnieje funkcja którą można dopasować dokonując konwersji typów argumentów, jeśli tak, dokonuje wiązania z zastosowaniem konwersji typów
Szablony funkcji sytuacje wyjątkowe często zdarza się, że funkcje wygenerowane z szablonu będą działać poprawnie(lub w ogóle będą poprawne) w większości przypadków, ale nie we wszystkich szablon z poprzedniego przykładu nie będzie działał poprawnie dla typu char* nienadajesięonwogólenp.dlatypu classdata public: int dzien, miesiac, rok; zawzględunabrakoperatora< cout << compare(1,2) << endl //-1 << compare(1.5,2.5) << endl //-1 <<compare( a, b ) <<endl //-1 << compare(pudelko(1.0,2.0,2.0),pudelko(2.0,1.5,4.2)) << endl//-1 <<compare("ala","ola") <<endl //1 (!) <<compare((string)"ala",(string)"ola") <<endl; //-1
Szablony funkcji funkcje specjalizowane wyjątki od sposobu generownia funkcji zdefiniowanego przez szablon można zdefiniować pisząc funkcję specjalizowaną funkcja specjalizowana to funkcja, której nazwa i typy parametrów pasują do szablonu, tyle że jest jest to normalna funkcja
Szablony funkcji funkcje specjalizowane template <class T> intcompare(t a,tb) if(a<b) return-1; else if(b<a) return 1; else return 0; int compare(const char* a, const char* b) return strcmp(a,b); intmain() cout << compare(1,2) << endl //-1 << compare(1.5,2.5) << endl //-1 <<compare( a, b ) <<endl //-1 << compare(pudelko(1.0,2.0,2.0),pudelko(2.0,1.5,4.2)) << endl//-1 <<compare("ala","ola") <<endl //-1 <<compare((string)"ala",(string)"ola") <<endl; //-1
podstawowe informacje szablon klasy jest sparametryzowaną definicją klasy szablon klasy definiuje się w zakresie globalnym Składnia: template< opis parametrów > class nazwaklasy... ;
przykład(bardzo typowy) Szablon klasy Stos, którego parametrem jest typ elementów przechowywanych na stosie. template <class T> class Stos public: Stos():n(0) Stos& push(t e) dane[n++]=e; return*this;// dodanie elementu Tpop() returndane[--n]; //pobranie elementu int empty() return n==0; // test czy pusty operator int() return n; // dodatkowy bajer private: Tdane[100]; intn; ;
klasa szablonowa po zdefniowaniu szablonu klas template< opis parametrów > class nazwaklasy... ; nazwą klasy szablonowej jest nazwaklasy<parametry> posługujemy się nią jak zwykłymi nazwami klas/typów w momencie napotkania takiej nazwy, kompilator generuję definicję klasy szablonowej dla podanych parametrów(jeśli wcześniej już tego nie zrobił)
użycie klasy szblonowej intmain() Stos<char> stosznakow; // generowana jest klasa Stos<char> // generowana jest klasa Stos<int> Stos<int> stosliczb; stosznakow.push( A ).push( l ).push( a ); stosliczb.push(1).push(2).push(3); Stos<char> drugistosznakow=stosznakow; // klasa Stos<char> już jest while(stosznakow) cout << stosznakow.pop(); cout << endl; while(stosliczb) cout << stosliczb.pop(); cout << endl; // bajer
parametry Szablon klasy może mieć wiele parametrów(separatorem jest przecinek) Parametrem szablonu klasy może być: typ(classnazwa) wartośćcałkowitastała(int nazwa) template<classtyp,introzmiar> takżestałewyrażeniebędąceadresemobiektuglobalnegolub funkcji globalnej(rzadsze zastosowanie)
definicje metod klasy szablonowej poza ciałem klasy definicje metod klasy szablonowej umieszczone poza ciałem klasy są w istocie szablonami definicji metod mają postać taką jak szablony funkcji, z tą oczywiście różnicą, że ich nazwę poprzedza się nazwą klasy szablonowej podobnie też jak w przypadku szablonów funkcji, można definiować metody specjalizowane
definicje metod klasy szablonowej poza ciałem klasy template <class T> class Stos public: Stos(); Stos& push(t e); Tpop(); itd private: Tdane[100]; intn; ; template<class T> Stos<T>::Stos() :n(0) template<class T> Stos<T>& Stos<T>::push(T e) dane[n++]=e; return*this; template<class T> TStos<T>::pop() returndane[--n]; itd.
definicje metod klasy szablonowej poza ciałem klasy (lupa) sątoszablonymetod template<class T> Stos<T>::Stos() :n(0) template<class T> Stos<T>& Stos<T>::push(T e) dane[n++]=e; return*this; template<class T> TStos<T>::pop() returndane[--n]; itd.
definicje metod klasy szablonowej poza ciałem klasy (lupa) nieodłączną częścią nazwy klasy szablonowej jest parametr(y) template<class T> Stos<T>::Stos() :n(0) template<class T> Stos<T>& Stos<T>::push(T e) dane[n++]=e; return*this; template<class T> TStos<T>::pop() returndane[--n]; itd.
definicje metod klasy szablonowej poza ciałem klasy (lupa) nazwa konstruktora(destruktora) nie jest nazwą klasy bez parametu template<class T> Stos<T>::Stos() :n(0) template<class T> Stos<T>& Stos<T>::push(T e) dane[n++]=e; return*this; template<class T> TStos<T>::pop() returndane[--n]; itd.
parametry nie będące typami przykład W szablonie stosów dodajemy parametr określający rozmiar. template <class T, int max> class Stos public: Stos():n(0) Stos& push(t e) dane[n++]=e; return*this; Tpop() returndane[--n]; intempty() returnn==0; operatorint() returnn; private: Tdane[max]; intn; ; intmain() Stos<char,20> stos; stos.push( A ).push( l ).push( a ); while(stos) cout<<stos.pop(); cout << endl;
klasa szablonowa jako klasa bazowa Klasa szablonowa może być klasą bazową innej klasy. Klasa szablonowa może być klasą bazową w szablonie klasy. template<class T> class K... ; classl:k<int>... template<class S> classm:k<int>...
klasa szablonowa jako klasa bazowa Klasa szablonowa może być klasą bazową innej klasy. Klasa szablonowa może być klasą bazową w szablonie klasy. template<class T> class K... ; classl:k<int>... template<class S> classm:k<int>...
szablon klasy jako klasa bazowa szablonuklasymożnaużyćjakoklasybazowejwinnym szablonie klasy parametry szablonu klasy bazowej muszą być parametrami szablonu klasy pochodnej albo muszą mieć ustaloną wartość template<class T, int max> class Stos... ; template<class S, int max> class lepszystos : K<S,max>... template<class S> class stosstulementowy : K<S,100>...
szablon klasy jako klasa bazowa szablonuklasymożnaużyćjakoklasybazowejwinnym szablonie klasy parametry szablonu klasy bazowej muszą być parametrami szablonu klasy pochodnej albo muszą mieć ustaloną wartość template<class T, int max> class Stos... ; template<class S, int max> class lepszystos : K<S,max>... template<class S> class stosstulementowy : K<S,100>...
składowe statyczne klas szablonowych Każda instancja klasy szablonowej ma swój komplet składowych statycznych.