Szablony funkcji

Transkrypt

Szablony funkcji
Zaawansowane programowanie w C++ (PCP)
Wykład 6 - szablony.
dr inż. Robert Nowak
- p. 1/15
Kolekcje i algorytmy
» Kolekcje i algorytmy
» „Reczna”
˛
modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
Pojecia
˛
niezależne od typu:
kolekcje (np. listy)
algorytmy (np. znajdowania najwiekszego
˛
elementu)
» Szablony - właściwości
» Przykład: std::pair
» Szablony funkcji
Mechanizmy eliminujace
˛ redundancje˛ kodu.
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia
klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
„reczna”
˛
modyfikacja kodu
wspólna klasa bazowa
wykorzystanie szablonów
- p. 2/15
„Reczna”
˛
modyfikacja kodu
» Kolekcje i algorytmy
» „Reczna”
˛
modyfikacja kodu
» Klasa bazowa
typedef int Element;//element przykładowego kontenera
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - właściwości
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia
klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
class WektorInt {
public:
explicit WektorInt(int size = 10);
//konstruktor kopiujacy,
˛
operator przypisania, destruktor
const Element& get(int idx) const;//Zwraca element o danym
Element& get(int idx);//Zwraca element o danym indeksie
//...
private:
˛
elementy wektora
Element* tab_;//Tablica przechowujaca
int size_;//Liczba elementów
int capacity_;//Wielkość tablicy
};
konieczność recznej
˛
zmiany kodu (błedy!)
˛
utrudnione wprowadzanie modyfikacji (wiele kopii kodu)
- p. 3/15
Klasa bazowa
» Kolekcje i algorytmy
» „Reczna”
˛
modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - właściwości
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia
klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
#include ¨Object.h¨
class WektorObj {
public:
explicit WektorInt(int size = 10);
//konstruktor kopiujacy,
˛
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 przechowujaca
˛
elementy wektora
//...
};
Wady:
narzuty pamieciowe
˛
i czasowe
problem typów wbudowanych
- p. 4/15
Zastosowanie szablonów
» Kolekcje i algorytmy
» „Reczna”
˛
modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - właściwości
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia
klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
tempate<class T> class Wektor {
public:
explicit Wektor(int size = 10);
//konstruktor kopiujacy,
˛
operator przypisania, destruktor
const T& get(int idx) const;//Zwraca element o danym indek
T& get(int idx);//Zwraca element o danym indeksie
void add(const T& val);//Dodaje element na koniec kolekcji
/* Dalsza cz˛
eść interfejsu klasy */
private:
T* tab_;//Tablica przechowujaca
˛
elementy wektora
int size_;//Liczba elementów
int capacity_;//Wielkość 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źników do klasy
- p. 5/15
Deklaracja szablonu klasy
» Kolekcje i algorytmy
» „Reczna”
˛
modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - właściwości
» 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:
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żny od dwu typów */ };
template<typename T, typename U = int>
class BinTree{ /* Domyślny parametr szablonu */ };
- p. 6/15
generowanie typu
» Kolekcje i algorytmy
» „Reczna”
˛
modyfikacja kodu
nazwa-szablonu < typ [,typ] >
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
Przykłady:
» generowanie typu
» Szablony - właściwości
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia
klas
Array<int> a;
std::vector<double> vd;
Graf<std::string, std::string> gr;
vector<vector<int> > vv;
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
Niejednoznaczności:
zbyt bliskie położenie kończacych
˛
>, np.
vector<vector<int>> v;
znak >> jest operatorem przesuniecia
˛
prawidłowe vector<vector<int> > v; (dodatkowa
spacja)
- p. 7/15
Szablony - właściwości
» Kolekcje i algorytmy
» „Reczna”
˛
modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
Szablony sa˛ mechanizmem czasu kompilacji
pozwalaja˛ współdzielić kod źródłowy
brak narzutów czasowych w czasie wykonania
» Szablony - właściwości
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia
klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
Organizacja plików źródłowych
definicja (a nie tylko deklaracja) szablonu musi być widoczna
w miejscu użycia
organizacja plików źródłowych
Kod nie jest kompilowany, jeżeli nie został użyty
- p. 8/15
Przykład: std::pair
» Kolekcje i algorytmy
» „Reczna”
˛
modyfikacja kodu
Definicja znajduje sie˛ w <utility>
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - właściwości
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
template<class _T1, class _T2>
struct pair {
typedef _T1 first_type;
typedef _T2 second_type;
» Problem typu
» Szablony kontra hierarchia
klas
_T1 first;//Pierwsza składowa
_T2 second;//Druga składowa
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
pair() : first(), second() { }
pair(const _T1& __a, const _T2& __b)
: first(__a), second(__b) { }
};
Przykłady użycia:
std::pair<std::string,bool> a(¨Ala¨,true);
a.first = ¨Ola¨;
a.second = false;
- p. 9/15
Szablony funkcji
» Kolekcje i algorytmy
» „Reczna”
˛
modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
Wzorce funkcji: pozwalaja˛ implementować algorytmy
niezależne od typu
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - właściwości
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia
klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
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;
}
- p. 10/15
Argumenty wzorca funkcji
» Kolekcje i algorytmy
» „Reczna”
˛
modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
Istnieje możliwość wyznaczania argumentów wzorca z
argumentów podanych w wywołaniu
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - właściwości
» Przykład: std::pair
template<typename T>
void printAll(const vector<T>& v, std::ostream& os) { /* ... *
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia
klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
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źnik */ }
int* pi = przydziel<int>();//Niemożliwa automatyczna specjaliz
- p. 11/15
Problem typu
» Kolekcje i algorytmy
» „Reczna”
˛
modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
Typowy problem - jawne wskazanie, że identyfikator jest
typem
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - właściwości
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia
klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
class Foo {
public:
typedef int Element;
/* dalsza cz˛
eść implementacji klasy Foo */
};
template<typename T> void f(const T& t) {
//Poniżej bł˛
ednie zakłada, że T::Element to nazwa składowej
T::Element e = 0;
//...
//Poniżej jawnie wskazano, że T::Element to nazwa typu
typename T::Element e = 0;
//...
};
- p. 12/15
Szablony kontra hierarchia klas
» Kolekcje i algorytmy
» „Reczna”
˛
modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - właściwości
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia
klas
Używaj szablonów gdy:
ważne sa˛ typy wbudowane
nie można utworzyć wspólnej klasy podstawowej
bardzo ważna jest efektywność
akceptowalna jest powtórna kompilacja przy dodawaniu
nowego typu
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
W przeciwnym wypadku używaj hierarchii klas.
- p. 13/15
Zasady tworzenia szablonów
» Kolekcje i algorytmy
» „Reczna”
˛
modyfikacja kodu
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - właściwości
» Przykład: std::pair
1.
2.
3.
4.
zaimplementować typ konkretny
przetestować go
przekształcić go w szablon
wygenerować i przetestować kilka różnych typów
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia
klas
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
- p. 14/15
Podział kodu wzorca na pliki
» Kolekcje i algorytmy
» „Reczna”
˛
modyfikacja kodu
Plik ¨kontener.h¨ - definicja klasy
» Klasa bazowa
» Zastosowanie szablonów
» Deklaracja szablonu klasy
» generowanie typu
» Szablony - właściwości
» Przykład: std::pair
» Szablony funkcji
» Argumenty wzorca funkcji
» Problem typu
» Szablony kontra hierarchia
klas
#ifndef KONTENER
#define KONTENER
template<typename T>
class Kontener { /* Definicja klasy i metod inline */ };
#include ¨kontener_impl.h¨
» Zasady tworzenia szablonów
» Podział kodu wzorca na pliki
#endif
Plik ¨kontener_impl.h¨ - implementacja metod wzorca
//Nie ma zabezpieczeń przed wielokrotnym dołaczaniem
˛
template<typename T>
T& Kontener<T>::get(int index) { /* Definicja metody */ }
Plik ¨kontener.cpp¨ - kod niezależny od typu T
- p. 15/15

Podobne dokumenty