• Nie Znaleziono Wyników

Programowanie obiektowe Wykład 5. C++: szablony

N/A
N/A
Protected

Academic year: 2021

Share "Programowanie obiektowe Wykład 5. C++: szablony"

Copied!
31
0
0

Pełen tekst

(1)

Wykład 5. C++: szablony

(2)

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.

(3)

przykład problemu: definiujemy funkcję porównującą...

...liczby całkowite:

int compare(int a, int b)

{ if(a<b) return 1; else if(b<a) return -1; else return 0; }

(4)

przykład problemu: definiujemy funkcję porównującą...

...liczby całkowite:

int compare(int a, int b)

{ if(a<b) return 1; else if(b<a) return -1; else return 0; }

...liczby rzeczywiste:

int compare(float a, float b)

{ if(a<b) return 1; else if(b<a) return -1; else return 0; }

(5)

przykład problemu: definiujemy funkcję porównującą...

...liczby całkowite:

int compare(int a, int b)

{ if(a<b) return 1; else if(b<a) return -1; else return 0; }

...liczby rzeczywiste:

int compare(float a, float b)

{ if(a<b) return 1; else if(b<a) return -1; else return 0; }

... i tak samo dla każdego innego typu

(6)

przykład problemu: definiujemy funkcję porównującą...

...liczby całkowite:

int compare(int a, int b)

{ if(a<b) return 1; else if(b<a) return -1; else return 0; }

...liczby rzeczywiste:

int compare(float a, float b)

{ if(a<b) return 1; else if(b<a) return -1; else return 0; }

... i tak samo dla każdego innego typu

... pod warunkiem, że ma zdefiniowany operator <

(7)

przykład problemu: definiujemy funkcję porównującą...

...liczby całkowite:

int compare(int a, int b)

{ if(a<b) return 1; else if(b<a) return -1; else return 0; }

...liczby rzeczywiste:

int compare(float a, float b)

{ if(a<b) return 1; else if(b<a) return -1; else return 0; }

...pudełka class Pudelko {

public:

float dl,sz,wy;

Pudelko(float d, float s, float w) : 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) return 1; else if(b<a) return -1; else return 0; }

(8)

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

(9)

przykład

class Pudelko {

public:

float dl,sz,wy;

Pudelko(float d, float s, float w) : dl(d), sz(s), wy(w) {}

int operator<(Pudelko& p) { return dl*sz*wy < p.dl*p.sz*p.wy; } };

template <class T>

int compare(T a, T b) {

if(a<b) return -1; else if(b<a) return 1; else return 0;

}

int main() {

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 }

(10)

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;

}

(11)

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>

void f(K a, L b, K c, M d) ...

pasuje do wywołania f(3,’e’,5,"Ala") ale do wywołania

f(3,’e’,’a’,"Ala")

nie.

(12)

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

(13)

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*

nie nadaje się on w ogóle np. dla typu

class Data { public:

int dzien, miesiac, rok;

}

za względu na brak operatora <

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

(14)

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

(15)

funkcje specjalizowane

template <class T>

int compare(T a, T b) {

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);

}

int main() {

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 }

(16)

podstawowe informacje

szablon klasy jest sparametryzowaną definicją klasy

szablon klasy definiuje się w zakresie globalnym Składnia:

template< opis˙parametrów >

class nazwaklasy {

...

};

(17)

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

T pop() { return dane[--n]; } // pobranie elementu

int empty() { return n==0; } // test czy pusty

operator int() { return n; } // dodatkowy bajer

private:

T dane[100];

int n;

};

(18)

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ł)

(19)

użycie klasy szblonowej

int main() {

Stos<char> stosznakow; // generowana jest klasa Stos<char>

Stos<int> stosliczb; // generowana jest klasa Stos<int>

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) // bajer

{

cout << stosznakow.pop();

}

cout << endl;

while(stosliczb) {

cout << stosliczb.pop();

}

cout << endl;

}

(20)

parametry

Szablon klasy może mieć wiele parametrów (separatorem jest przecinek)

Parametrem szablonu klasy może być:

typ (class nazwa)

wartość całkowita stała (int nazwa)

template < class Typ, int rozmiar >

także stałe wyrażenie będące adresem obiektu globalnego lub

funkcji globalnej (rzadsze zastosowanie)

(21)

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

(22)

definicje metod klasy szablonowej poza ciałem klasy

template <class T>

class Stos {

public:

Stos();

Stos& push(T e);

T pop();

itd private:

T dane[100];

int n;

};

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>

T Stos<T>::pop() { return dane[--n]; } itd.

(23)

definicje metod klasy szablonowej poza ciałem klasy (lupa)

są to szablony metod

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>

T Stos<T>::pop() return dane[--n];

itd.

(24)

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>

T Stos<T>::pop() return dane[--n];

itd.

(25)

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>

T Stos<T>::pop() return dane[--n];

itd.

(26)

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; } T pop() { return dane[--n]; }

int empty() { return n==0; } operator int() { return n; }

private:

T dane[max];

int n;

};

int main() {

Stos<char,20> stos;

stos.push(’A’).push(’l’).push(’a’);

while(stos) { cout << stos.pop(); } cout << endl;

}

(27)

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 {

...

};

class L : K<int>

{ ...

}

template<class S>

class M : K<int>

{ ...

}

(28)

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 {

...

};

class L : K<int>

{ ...

}

template<class S>

class M : K<int>

{ ...

}

(29)

szablon klasy jako klasa bazowa

szablonu klasy można użyć jako klasy bazowej w innym 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>

{ ...

}

(30)

szablon klasy jako klasa bazowa

szablonu klasy można użyć jako klasy bazowej w innym 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>

{ ...

}

(31)

składowe statyczne klas szablonowych

Każda instancja klasy szablonowej ma swój komplet składowych

statycznych.

Cytaty

Powiązane dokumenty

Tworzenie prezentacji multimedialnych: animacja tekstu i grafiki na slajdach, efekty przejść przy zmianie slajdów, wstawianie dźwięku i filmów, pokaz slajdów,

W wielostronnym programie rozwoju i upowszechniania kultury w powiecie włoszczowskim na lata 1966-1970 opracowanym przez PPRN we Włoszczowie znajduje się

Załącznik nr 1 do Uchwały Nr 35/2019 Rady Wydziału Stosowanych Nauk Społecznych i Resocjalizacji z dnia 13 listopada 2019 roku w sprawie szczegółowych zasad rozliczania

n Dla obiektu, którego klasy nie można jednoznacznie określić na etapie kompilacji, odwołania do metody, bądź metod zadeklarowanych jako wirtualne będą się odbywały

As you walk into the room, first thing you notice is my huge and extremely comfortable bed, which fills almost the half of the room. That’s a very

(4 pkt) W klasie Stos zdeniuj metody dost¦pu, wstawiania oraz usuwania elementu stosu  pa- mi¦taj, »e do stosu dost¦p jest tylko z jednej strony.. (4 pkt) W klasie Stos

DODATKOWE - na dodatkowe punkty lub wy»sz¡ ocen¦ (zadania 1-3 musz¡ by¢ wykonane!) Do realizacji podobnego jak wy»ej zadania i budowy klas wyj¡tków wykorzystaj bibliotek¦

„wodotryskami” i wolelibyśmy, aby przyrząd nie wykonał sam całego doświad- czenia za ucznia/studenta, wówczas świetną alternatywą dla zakupu chronogra- fu, może być