- p. 1/15
Zaawansowane programowanie w C++ (PCP)
Wykład 6 - szablony.
dr in˙z. Robert Nowak
» Kolekcje i algorytmy
» „R ˛eczna” modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - wła´sciwo´sci
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
Kolekcje i algorytmy
Poj ˛ecia niezale˙zne od typu:
kolekcje (np. listy)
algorytmy (np. znajdowania najwi ˛ekszego elementu) Mechanizmy eliminuj ˛ ace redundancj ˛e kodu.
„r ˛eczna” modyfikacja kodu
wspólna klasa bazowa
wykorzystanie szablonów
» Kolekcje i algorytmy
» „R ˛eczna” modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - wła´sciwo´sci
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
- p. 3/15
„R ˛eczna” modyfikacja kodu
typedef int Element;//element przykładowego kontenera
class WektorInt { public:
explicit WektorInt(int size = 10);
//konstruktor kopiuj ˛ acy, operator przypisania, destruktor const Element& get(int idx) const;//Zwraca element o danym Element& get(int idx);//Zwraca element o danym indeksie //...
private:
Element* tab_; //Tablica przechowuj ˛ aca elementy wektora int size_;//Liczba elementów
int capacity_;//Wielko´ s´ c tablicy };
konieczno´s´c r ˛ecznej zmiany kodu (bł ˛edy!)
utrudnione wprowadzanie modyfikacji (wiele kopii kodu)
» Kolekcje i algorytmy
» „R ˛eczna” modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - wła´sciwo´sci
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
Klasa bazowa
#include ¨Object.h¨
class WektorObj { public:
explicit WektorInt(int size = 10);
//konstruktor kopiuj ˛ acy, operator przypisania, destruktor const Object& get(int idx) const;//Zwraca element o danym Object& get(int idx);//Zwraca element o danym indeksie //...
private:
Object** tab_; //Tablica przechowuj ˛ aca elementy wektora //...
};
Wady:
narzuty pami ˛eciowe i czasowe
problem typów wbudowanych
» Kolekcje i algorytmy
» „R ˛eczna” modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - wła´sciwo´sci
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
- p. 5/15
Zastosowanie szablonów
tempate<class T> class Wektor { public:
explicit Wektor(int size = 10);
//konstruktor kopiuj ˛ acy, operator przypisania, destruktor
const T& get(int idx) const;//Zwraca element o danym indeksie T& get(int idx);//Zwraca element o danym indeksie
void add(const T& val);//Dodaje element na koniec kolekcji /* Dalsza cz˛ e´ s´ c interfejsu klasy */
private:
T* tab_; //Tablica przechowuj ˛ aca elementy wektora int size_;//Liczba elementów
int capacity_;//Wielko´ s´ c tablicy };
Wektor<int> v;//Kolekcja liczb całkowitych v.add(3); v.add(4);//Operacje na kolekcji
Wektor<Data> vd;//Kolekcja obiektów klasy Data
Wektor<Figura*> vf; //Kolekcja wska´ zników do klasy
» Kolekcje i algorytmy
» „R ˛eczna” modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - wła´sciwo´sci
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
Deklaracja szablonu klasy
Deklaracja szablonu:
deklaracja-wzorca:
template < lista-parametrów-wzorca > deklaracja
lista-parametrów-wzorca:
parametr-wzorca [,lista-parametrów-wzorca]
parametr-wzorca:
class identyfikator [= id-typu ]
typename identyfikator [= id-typu ]
Przykłady:
template<class T> class Array { /* oparty o jeden typ */ };
template<typename T, typename U>
class Graf{ /* zale˙ zny od dwu typów */ };
template<typename T, typename U = int>
class BinTree{ /* Domy´ slny parametr szablonu */ };
» Kolekcje i algorytmy
» „R ˛eczna” modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - wła´sciwo´sci
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
- p. 7/15
generowanie typu
nazwa-szablonu < typ [,typ] >
Przykłady:
Array<int> a;
std::vector<double> vd;
Graf<std::string, std::string> gr;
vector<vector<int> > vv;
Niejednoznaczno´sci:
zbyt bliskie poło˙zenie ko ´ncz ˛ acych >, np.
vector<vector<int>> v;
znak >> jest operatorem przesuni ˛ecia
prawidłowe vector<vector<int> > v; (dodatkowa
spacja)
» Kolekcje i algorytmy
» „R ˛eczna” modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - wła´sciwo´sci
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
Szablony - wła ´sciwo ´sci
Szablony s ˛ a mechanizmem czasu kompilacji
pozwalaj ˛ a współdzieli´c kod ´zródłowy
brak narzutów czasowych w czasie wykonania Organizacja plików ´zródłowych
definicja (a nie tylko deklaracja) szablonu musi by´c widoczna w miejscu u˙zycia
organizacja plików ´zródłowych
Kod nie jest kompilowany, je˙zeli nie został u˙zyty
» Kolekcje i algorytmy
» „R ˛eczna” modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - wła´sciwo´sci
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
- p. 9/15
Przykład: std::pair
Definicja znajduje si ˛e w <utility>
template<class _T1, class _T2>
struct pair {
typedef _T1 first_type;
typedef _T2 second_type;
_T1 first;//Pierwsza składowa _T2 second;//Druga składowa
pair() : first(), second() { }
pair(const _T1& __a, const _T2& __b) : first(__a), second(__b) { } };
Przykłady u˙zycia:
std::pair<std::string,bool> a(¨Ala¨,true);
a.first = ¨Ola¨;
a.second = false;
» Kolekcje i algorytmy
» „R ˛eczna” modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - wła´sciwo´sci
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
Szablony funkcji
Wzorce funkcji: pozwalaj ˛ a implementowa´c algorytmy niezale˙zne od typu
template<typename T>
void std::swap(T& a, T& b) { T tmp = a;
a = b;
b = tmp;
}
template<typename T>
void printAll(const vector<T>& v, std::ostream& os) { for(size_t i = 0; i != v.size(); ++i)
os << v[i] << ",";
os << endl;
}
» Kolekcje i algorytmy
» „R ˛eczna” modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - wła´sciwo´sci
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
- p. 11/15
Argumenty wzorca funkcji
Istnieje mo˙zliwo´s´c wyznaczania argumentów wzorca z argumentów podanych w wywołaniu
template<typename T>
void printAll(const vector<T>& v, std::ostream& os) { /* ... * vector<int> w;
//dodanie elementów do wektora
printAll(w,cout);//printAll<int>(w,cout) template<typename T> T* przydziel()
{ /* Tworzy obiekt i zwraca wska´ znik */ }
int* pi = przydziel<int>(); //Niemo˙ zliwa automatyczna specjalizacja
» Kolekcje i algorytmy
» „R ˛eczna” modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - wła´sciwo´sci
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
Problem typu
Typowy problem - jawne wskazanie, ˙ze identyfikator jest typem
class Foo { public:
typedef int Element;
/* dalsza cz˛ e´ s´ c implementacji klasy Foo */
};
template<typename T> void f(const T& t) {
//Poni˙ zej bł˛ ednie zakłada, ˙ ze T::Element to nazwa składowej T::Element e = 0;
//...
//Poni˙ zej jawnie wskazano, ˙ ze T::Element to nazwa typu typename T::Element e = 0;
//...
};
» Kolekcje i algorytmy
» „R ˛eczna” modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - wła´sciwo´sci
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
- p. 13/15
Szablony kontra hierarchia klas
U˙zywaj szablonów gdy:
wa˙zne s ˛ a typy wbudowane
nie mo˙zna utworzy´c wspólnej klasy podstawowej
bardzo wa˙zna jest efektywno´s´c
akceptowalna jest powtórna kompilacja przy dodawaniu nowego typu
W przeciwnym wypadku u˙zywaj hierarchii klas.
» Kolekcje i algorytmy
» „R ˛eczna” modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - wła´sciwo´sci
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
Zasady tworzenia szablonów
1. zaimplementowa´c typ konkretny 2. przetestowa´c go
3. przekształci´c go w szablon
4. wygenerowa´c i przetestowa´c kilka ró˙znych typów
» Kolekcje i algorytmy
» „R ˛eczna” modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - wła´sciwo´sci
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
- p. 15/15