PDF

Transkrypt

PDF
Programowanie obiektowe
Wykład 9
Dariusz Wardowski
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
1/15
Programowanie obiektowe
Wykład 9
Parametry domyślne
Definiując szablon możemy dla danego parametru typu ustalić wartość domyślną, tzn. wartość,
którą dany parametr osiągnie, gdy podczas konkretyzacji wartość typu zostanie pominięta.
template <typename T1, typename T2 = char>
class A
{
…
};
Jeżeli podczas konkretyzacji szablonu A, nie wskażemy wartości dla parametru typu T2, zostanie
użyty typ char.
A<int,double> a1;
A<char*> a2;
//T1 = int, T2 = double
//T1 = char*, T2 = char
template <typename T = int>
class B
{
…
};
B<string> b1; // T = string
B<> b2; // T = int
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
2/15
Programowanie obiektowe
Wykład 9
Wartości domyślne w szablonach funkcji
Definiując szablon klasy możemy korzystać zarówno z wartości domyślnych dla parametrów typu
jaki i wartości domyślnych dla argumentów wyrażeń (nie-typów).
Definiując szablon funkcji możemy używać wartości domyślne co najwyżej dla argumentów
wyrażeń.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
3/15
Programowanie obiektowe
Wykład 9
Niejawna konkretyzacja szablonów
W przypadku, gdy na podstawie szablonu deklarujemy obiekt, określając żądany typ, korzystamy
z niejawnej konkretyzacji szablonu. W takim przypadku kompilator uszczegóławia definicję klasy
według schematu zadanego przez szablon tej klasy.
A<int> a;
niejawna konkretyzacja szablonu
Ponadto kompilator zastosuje niejawną konkretyzację wówczas, gdy zostanie użyty obiekt
konkretyzowanej klasy:
A<int>* wsk;
obiekt klasy jeszcze nie jest użyty, więc brak konkretyzacji
wsk = new A<int>(); obiekt klasy A<int> jest tworzony, więc musi nastąpić konkretyzacja
szablonu
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
4/15
Programowanie obiektowe
Wykład 9
Jawna konkretyzacja szablonów
Jawna konkretyzacja zachodzi wówczas, gdy podczas deklaracji klasy użyte jest słowo kluczowe
template oraz podane są dokładne wartości typów. Definicja takiej klasy jest tworzona nawet
jeśli nie tworzony jest obiekt tej klasy. Np.:
template class A<double>;
//możemy teraz korzystać z klasy A<double>
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
5/15
Programowanie obiektowe
Wykład 9
Jawne uszczegółowienie szablonu
Jawne uszczegółowienie polega na utworzeniu szablonu dla konkretnej wartości typu lub typów.
Ma to zastosowanie w przypadku, gdy dla konkretnego typu chcemy zmienić działanie szablonu.
template <typename T>
class LiczbaTP
{
private:
T x;
public:
LiczbaTP(T _x) : x(_x) {}
T dodaj(LiczbaTP L);
};
template <typename T>
T LiczbaTP<T>::dodaj(LiczbaTP L)
{
return x + L.x;
}
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
6/15
Programowanie obiektowe
Wykład 9
Jawne uszczegółowienie szablonu c.d.
template <> class LiczbaTP<char>
{
private:
char x;
public:
LiczbaTP(char _x) : x(_x) {}
char* dodaj(LiczbaTP L);
bool czyWiekszaOd(const LiczbaTP L);
};
char* LiczbaTP<char>::dodaj(LiczbaTP L)
{
char* trzy = new char[3];
trzy[0] = x;
trzy[1] = L.x;
trzy[2] = '\0';
return trzy;
}
LiczbaTP<int> L1(2), L1(5); //użyto definicji ogólnej szablonu
cout << L1.dodaj(L2); //wypisze 7
LiczbaTP<char> C1(‘a’), C2(‘b’); //użyto definicji uszczegółowionej
cout << C1.dodaj(C2); //wypisze „ab”
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
7/15
Programowanie obiektowe
Wykład 9
Uszczegółowienie częściowe
Stosując tego typu uszczegółowienie możemy skonkretyzować tylko niektóre parametry typu.
Zatem definicja takiego szablonu tylko po części ulega ograniczeniu do konkretnego typu.
template <typename T1, typename T2>
class A
{
szablon ogólny
…
};
template <typename T2>
class A<int,T2>
{
…
};
template <>
class A<int,int>
{
…
};
A<char,char> a1;
A<int,double> a2;
A<int,int> a3;
parametr T1 został uszczegółowiony
do parametru int
parametry T1, T2 zostały uszczegółowione
do parametru int
//użyto ogólny szablon A
//użyto częściowego uszczegółowienia A<int,T2>
//użyto jawnego uszczegółowienia A<int,int>
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
8/15
Programowanie obiektowe
Wykład 9
Zagnieżdżanie szablonów
W ramach definicji jednego szablonu dopuszczalne jest definiowanie wewnętrznego szablonu
składowego.
template <typename U>
class Para
{
private:
template <typename V>
class Elem
{
private:
V x;
public:
Elem(V _x = 0) {x=_x;}
V get() const {return V;}
};
Elem<int> e1;
Elem<U> e2;
public:
Para(U u, int i) : e1(i), e2(u) {}
…
};
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
9/15
Programowanie obiektowe
Wykład 9
Szablony a funkcje zaprzyjaźnione
Definiując szablon, możemy stosować funkcje zaprzyjaźnione. Możemy wtedy wyróżnić
następujące przypadki:
•Nieszablonowe funkcje zaprzyjaźnione, czyli takie, które nie są zależne od parametru typu.
•Funkcje zaprzyjaźnione, których typ argumentów jest zależny od szablonu.
•Funkcje zaprzyjaźnione szablonowe, ale takie, które nie są związane z szablonem.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
10/15
Programowanie obiektowe
Wykład 9
Nieszablonowe funkcje zaprzyjaźnione
template <typename T>
class A
{
private:
int x;
public:
A();
friend void f();
};
Funkcja f jest funkcją zaprzyjaźnioną z klasą będącą dowolną konkretyzacją szablonu A. Np. f
jest zaprzyjaźniona z następującymi klasami:
A<int>, A<double>, A<char*>, A<string>, A<bool>, … .
W powyższej deklaracji funkcji f brak jest argumentów. Jaki jest zatem sens zaprzyjaźniać tego
typu funkcje z klasą?
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
11/15
Programowanie obiektowe
Wykład 9
Nieszablonowe funkcje zaprzyjaźnione z argumentami szablonowymi
template <typename T>
class A
{
private:
int x;
public:
A();
friend void f(A &);
};
źle!!!
W celu przekazania do argumentu funkcji klasę szablonową, należy wskazać jej
uszczegółowienie.
friend void f(A<T> &);
Ponieważ powyższa funkcja nie jest szablonowa, możemy zatem podać definicję tylko dla
konkretnych typów.
void f(A<int> & a)
{
cout << a.x + 1;
}
void f(A<char> & a)
{
cout << (int)a.x;
}
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
12/15
Programowanie obiektowe
Wykład 9
Szablonowe funkcje zaprzyjaźnione związane z szablonem
W celu zdefiniowania szablonowej funkcji zaprzyjaźnionej związanej z szablonem należy w
pierwszej kolejności przed definicją klasy ją zadeklarować. Następnie deklarujemy szablon wraz z
wcześniej zadeklarowaną funkcją zaprzyjaźnioną.
template <typename T> void f(T &);
template <typename T> void g();
template <typename TYP>
class PrzykladTP
{
private:
TYP x;
static int i;
public:
friend void f<>(PrzykladTP<TYP> &);
friend void g<TYP>();
};
template <typename T>
void g()
{
cout << PrzykladTP<T>::i;
}
template <typename T>
int PrzykladTP<T>::i=0;
template <typename T>
void f(T & t)
{
cout << t.x;
}
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
13/15
Programowanie obiektowe
Wykład 9
Szablonowe funkcje zaprzyjaźnione niezwiązane z szablonem
To takie funkcje, których każde uszczegółowienie jest funkcją zaprzyjaźnioną dla każdego
uszczegółowienia danej klasy.
template <typename T>
class A
{
private:
T x;
public:
A(T _x) : x(_x) {}
template <typename U>
friend void f(U &);
};
int main()
{
A<double> a1(2.3);
A<char> a2(‘h’);
f(a1);
f(a2);
return 0;
}
template <typename U>
void f(U & u)
{
cout << u.x << endl;
}
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
14/15
Programowanie obiektowe
Wykład 9
Dziękuję za uwagę!

dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
15/15