w23 szablony klas


Szablony klas
Potrzeba istnienia
" przykład: program pomagający w dokonaniu wyboru
określonej ilości elementów jakiegoś typu (np. zawodników
do dru\yny)
" dwie klasy  klasa opisująca pojedynczy element (tu:
gracz) oraz klasa słu\ąca do opisu zbioru elementów
(klasa pojemnikowa  tu: druzyna)
#include
#include
class gracz {
char imie[20];
char nazwisko[20];
int wzrost;
int cena;
public:
gracz(char *i="", char *n="", int w=0, int c=0) : wzrost(w), cena(c)
{
strcpy(imie,i);
strcpy(nazwisko,n);
}
friend ostream & operator<<(ostream &os, const gracz & g)
{
os << g.imie << " " << g.nazwisko << ", wzrost: "
<< g.wzrost << ", cena: " << g.cena << " M$";
return os;
}
};
class druzyna {
static const int max = 5;
gracz *tab[max];
int ilu_gra;
char *opis;
public:
druzyna(char *jaka);
void wypusc(gracz *w) {tab[ilu_gra++]=w;}
void zdejmij(int nr);
void sklad();
void czy_wypuszczasz(gracz *w);
};
druzyna::druzyna(char* jaka)
{
opis=jaka;
for(int k=0; k ilu_gra=0;
}
void druzyna::zdejmij(int ktory)
{
for(int k=ktory-1;k tab[k]=tab[k+1];
tab[max-1]=NULL;
ilu_gra--;
}
void druzyna::sklad()
{
cout << "Druzyna " << opis << " - aktualny sklad: " << endl;
for(int k=0; k {
if(tab[k])
{
cout << " " << (k+1) << ". " << *tab[k] << endl;
}
}
}
void druzyna::czy_wypuszczasz(gracz *w)
{
cout << "Nowy gracz: " << *w << "\nCzy wypuszczasz ? [t/n] : ";
char tn;
cin >> tn;
if (tn=='t'||tn=='T')
{
if(ilu_gra>=max)
{
cout << "Druzyna " << opis
<< " bedzie miala za duzo graczy !!!\n";
sklad();
cout << "Ktorego zdjac [nr 1 : " << max <<"] ? : ";
int nr;
cin >> nr;
zdejmij(nr);
}
wypusc(w);
}
sklad();
}
main()
{
gracz g0("Jason","Kidd",193,120);
gracz g1("LeBron","James",203,65);
gracz g2("Allen","Iverson",183,80);
gracz g3("Dirk","Nowitzki",213,50);
gracz g4("Yao","Ming",229,95);
gracz g5("Shaquille","O'Neal",216,105);
gracz g6("Vince","Carter",198,65);
druzyna d("Dream Team");
d.czy_wypuszczasz(&g0);
d.czy_wypuszczasz(&g1);
d.czy_wypuszczasz(&g2);
d.czy_wypuszczasz(&g3);
d.czy_wypuszczasz(&g4);
d.czy_wypuszczasz(&g5);
d.czy_wypuszczasz(&g6);
system("Pause");
}
" klasa gracz: dane składowe + konstruktor + operator<<
" klasa dru\yna:
o rozmiar tablicy danych  static const
o kolekcja danych typu gracz  tablica wskazników do
obiektów
o metody klasy druzyna:
konstruktor
wypusc  dodanie elementu do kolekcji
zdejmij  usunięcie elementu z kolekcji
sklad  wypisanie zawartości kolekcji
czy_wypuszczasz  pyta o zgodę na
powiększenie kolekcji, pilnuje by nie był
przekroczony maksymalny rozmiar kolekcji
" inni trenerzy te\ chcą taki program  potrzeba nowych
wersji (dla innych klas typu gracz, innych rozmiarów)
" schemat tego typu  wszędzie, gdzie chcemy zawiadywać
kolekcją
" potrzeba narzędzia do produkcji klas pojemnikowych na
wzór klasy druzyna
Sposób definicji
" prostszy przykład
o pojemnik na liczby int:
class schowek_int {
int zawartosc;
public:
int wyjmij() {return zawartosc;}
void wsadz(int a) {zawartosc=a;}
};
o pojemnik na znaki:
class schowek_char {
char zawartosc;
public:
char wyjmij() {return zawartosc;}
void wsadz(char a) {zawartosc=a;}
};
o podobnie  pojemniki na float, long, double itp.
o definicje tych wszystkich klas mogą być zastąpione
definicją szablonu klas:
template
class schowek {
typA zawartosc;
public:
typA wyjmij() {return zawartosc;}
void wsadz(typA a) {zawartosc=a;}
};
o przykład u\ycia:
#include
#include
template
class schowek {
typA zawartosc;
public:
typA wyjmij() {return zawartosc;}
void wsadz(typA a) {zawartosc=a;}
};
main()
{
schowek i1; //generacja klasy, definicja obiektu
schowek i2; //generacja klasy, definicja obiektu
schowek i3; //tylko definicja obiektu
schowek w; //generacja klasy, definicja obiektu
int x=5;i1.wsadz(7);
i2.wsadz('Y');
w.wsadz(&x);
cout << "zawartosc schowka int: " << i1.wyjmij() << endl;
cout << "zawartosc schowka char: " << i2.wyjmij() << endl;
cout << "zawartosc schowka *int: " << *w.wyjmij() << endl;
}
" składnia definicji szablonu funkcji:
o słowo kluczowe template
o lista parametrów szablonu (ujętych w nawiasy ostre)
 nie mo\e być pusta
o słowo kluczowe class
o nazwa szablonu  dopuszczalna nazwa obiektu w C,
unikalna tj. ró\na od nazwy wszystkich innych
obiektów w programie  klas nie przeładowujemy
o ciało szablonu klasy
" wywołanie szablonu klas  natknięcie się w tekście
programu na pierwsze u\ycie nazwy szablonu z listą
parametrów aktualnych
" nazwa klasy szablonowej (wygenerowanej przez szablon):
nazwa_szablonu
" uwaga  nazwy klasy szablonowej, której parametrem
aktualnym jest inna klasa szablonowej:
template
class pojemnik;
pojemnik > aa;
" wielkości, które mogą być parametrami aktualnymi
(formalnymi) klasy:
o nazwa typu (jako parametr formalny poprzedzony
słowem kluczowym class)
o stałe wyra\enie będące: wartością całkowitą ||
adresem obiektu globalnego || adresem funkcji
globalnej || adresem statycznego składnika klasy
" definiowanie metod klasy szablonowej
o definiowanie wewnątrz ciała klasy  jak dla zwykłej
klasy; tak zdefiniowane metody są inline
o poza ciałem klasy (w ciele klasy tylko deklaracja);
definicja jest dokonana jako szablon funkcji
" przykład (uogólnienie przykładu 1):
#include
#include
class gracz {
char imie[20];
char nazwisko[20];
int wzrost;
int cena;
public:
gracz(char *i="", char *n="", int w=0, int c=0) : wzrost(w), cena(c)
{
strcpy(imie,i);
strcpy(nazwisko,n);
}
friend ostream & operator<<(ostream &os, const gracz & g)
{
os << g.imie << " " << g.nazwisko << ", wzrost: "
<< g.wzrost << ", cena: " << g.cena << " M$";
return os;
}
};
class tenisista {
char imie[20];
char nazwisko[20];
int punkty_ATP;
public:
tenisista(char *i="", char *n="", int p=0) : punkty_ATP(p)
{
strcpy(imie,i);
strcpy(nazwisko,n);
}
friend ostream & operator<<(ostream &os, const tenisista & g)
{
os << g.imie << " " << g.nazwisko << ", "
<< g.punkty_ATP << " punktow ATP";
return os;
}
};
template
class druzyna {
typA *tab[max];
int ilu_gra;
char *opis;
public:
druzyna(char *jaka);
void wypusc(typA *w) {tab[ilu_gra++]=w;}
void zdejmij(int nr);
void sklad();
void czy_wypuszczasz(typA *w);
};
template
druzyna::druzyna(char* jaka)
{
opis=jaka;
for(int k=0; k ilu_gra=0;
}
template
void druzyna::zdejmij(int ktory)
{
for(int k=ktory-1;k tab[k]=tab[k+1];
tab[max-1]=NULL;
ilu_gra--;
}
template
void druzyna::sklad()
{
cout << "Druzyna " << opis << " - aktualny sklad: " << endl;
for(int k=0; k {
if(tab[k])
{
cout << " " << (k+1) << ". " << *tab[k] << endl;
}
}
}
template
void druzyna::czy_wypuszczasz(typA *w)
{
cout << "Nowy gracz: " << *w << "\nCzy wypuszczasz ? [t/n] : ";
char tn;
cin >> tn;
if (tn=='t'||tn=='T')
{
if(ilu_gra>=max)
{
cout << "Druzyna " << opis
<< " bedzie miala za duzo graczy !!!\n";
sklad();
cout << "Ktorego zdjac [nr 1 : " << max <<"] ? : ";
int nr;
cin >> nr;
zdejmij(nr);
}
wypusc(w);
}
sklad();
}
main()
{
gracz g0("Jason","Kidd",193,120);
gracz g1("LeBron","James",203,65);
gracz g2("Allen","Iverson",183,80);
gracz g3("Dirk","Nowitzki",213,50);
gracz g4("Yao","Ming",229,95);
gracz g5("Shaquille","O'Neal",216,105);
gracz g6("Vince","Carter",198,65);
druzyna d("Dream Team");
d.czy_wypuszczasz(&g0);
d.czy_wypuszczasz(&g1);
d.czy_wypuszczasz(&g2);
d.czy_wypuszczasz(&g3);
d.czy_wypuszczasz(&g4);
d.czy_wypuszczasz(&g5);
d.czy_wypuszczasz(&g6);
tenisista t1("Rafael","Nadal",894);
tenisista t2("Juan Carlos","Ferrero",216);
tenisista t3("Carlos","Moya",196);
tenisista t4("David","Ferrer",296);
tenisista t5("Tommy","Robredo",475);
cout << "\n=======================================\n";
druzyna t("Hiszpania");
t.czy_wypuszczasz(&t1);
t.czy_wypuszczasz(&t2);
t.czy_wypuszczasz(&t3);
t.czy_wypuszczasz(&t4);
t.czy_wypuszczasz(&t5);
}
" pełna nazwa konstruktora klasy szablonowej
nazwa_szabl_klasy::nazwa_szabl_klasy(arg& )
np.:
druzyna::druzyna( Hiszpania )
" typ i pełna nazwa metody klasy szablonowej
typ_wyniku nazwa_szabl_klasy::nazwa_metody(arg& )
np.:
void druzyna::zdejmij(ktory)
" wywołanie szablonu klasy  gdy po raz pierwszy
posłu\ymy się nazwą klasy szablonowej; mo\e to być
o definicja obiektu klasy szablonowej
druzyna d1( Prokom ); // szablon działa
druzyna d2( Anwil ); // teraz nie
o definicja wskaznika do obiektów klasy szablonowej
druzyna *wd;
o deklaracja funkcji zawierającej odniesienie do klasy
szablonowej
void gra(druzyna d);
o u\ycie klasy szablonowej jako klasy podstawowej w
dziedziczeniu
class team : public druzyna {
gracz kadra[12];
// inne zmiany
&
};
Specjalizowane klasy szablonowe
" jak w przypadku szablonów klas  stosowane w sytuacji,
gdy
o mamy działający szablon klas
o chcemy, by dla pewnego zestawu parametrów szablonu
klasa była zdefiniowana inaczej ( nieszablonowo ) (lub
te\  klasa nie da się zdefiniować poprzez szablon)
Przykład:
#include
#include
template
class skarbonka {
typA suma;
public:
skarbonka() : suma(0) { }
void dodaj(typA porcja) {suma=suma+porcja;}
typA rozbij();
};
template
A skarbonka::rozbij()
{
A aux=suma;
suma=0;
return aux;
}
class skarbonka {
char* suma;
public:
skarbonka() : suma(NULL) {;}
void dodaj(char* zapis);
char* rozbij();
~skarbonka()
{
if(suma)
{
cout << "Likwidacja obiektu przed jego oproznieniem !!!\n";
delete suma;
}
}
};
void skarbonka::dodaj(char* zapis)
{
if(!suma)
{
suma=new char(strlen(zapis)+1);
suma[0]='\0';
}
else
{
char* aux=suma;
suma=new char(strlen(aux)+strlen(zapis)+1);
strcpy(suma,aux);
delete aux;
}
strcat(suma,zapis);
}
char* skarbonka::rozbij()
{
char* aux=suma;
suma=NULL;
return aux;
}
main()
{
skarbonka swinka;
swinka.dodaj(10.50);
swinka.dodaj(3.30);
float suma_1;
suma_1=swinka.rozbij();
cout << "W swince Kasi bylo: " << suma_1 << " zl." << endl;
skarbonka konto;
konto.dodaj(10000L);
konto.dodaj(25000L);
konto.dodaj(33333L);
cout << "Saldo konta na Kajmanach: " << konto.rozbij() << " $.\n";
{
skarbonka notes;
notes.dodaj("Litwo, ojczyzno moja, ty jestes jak zdrowie\n");
notes.dodaj("Byc albo nie byc - oto jest pytanie\n");
cout << "Zapiski dnia dzisiejszego : \n" << notes.rozbij();
notes.dodaj("W co sie bawic, w co sie bawic ...\n");
}
}
============================================
W swince Kasi bylo: 13.8 zl.
Saldo konta na Kajmanach: 68333 $.
Zapiski dnia dzisiejszego :
Litwo, ojczyzno moja, ty jestes jak zdrowie
Byc albo nie byc - oto jest pytanie
Likwidacja obiektu przed jego oproznieniem !!!
" definicja specjalizowanej klasy szablonowej to definicja
klasy (nie szablonu)  do szablonu klas nawiązuje nazwą
(poszerzoną o specyfikację parametru)
" wyjątkowość tej klasy  mogłaby być zdefiniowana
poprzez szablon
" miejsce definicji  po definicji szablonu klas; inaczej
kompilator nie dopuści <& > jako części nazwy klasy
" specjalizowana klasa szablonowa mo\e mieć inne
składniki ni\ szablon (w przykładzie powy\ej  destruktor)
Specjalizacja funkcji składowej szablonu klas
" stosowna, gdy chcemy zastąpić tylko metodę klasy
szablonowej własną,  nieszablonową definicją
" robimy to pisząc własną definicję metody dla parametru
szablonu, dla którego jest to potrzebne (czyli  jest to
funkcja specjalizowana dla pewnej wybranej klasy)
Przykład:
#include
template
class skarbonka {
typA suma;
public:
skarbonka() : suma(0) {;}
void dodaj(typA porcja) {suma=suma+porcja;}
typA rozbij();
};
template
A skarbonka
::rozbij()
{
A aux=suma;
suma=0;
return aux;
}
void skarbonka::dodaj(long porcja)
{
suma+=porcja;
cout << "Dodano " << porcja << " $ - aktualne saldo: "
<< suma <<" $.\n";
}
main()
{
skarbonka swinka;
swinka.dodaj(10.50);
swinka.dodaj(3.30);
float suma_1;
suma_1=swinka.rozbij();
cout << "W swince Kasi bylo: " << suma_1 << " zl." << endl;
skarbonka konto;
konto.dodaj(10000L);
konto.dodaj(25000L);
konto.dodaj(33333L);
cout << "Saldo konta na Kajmanach: " << konto.rozbij() << " $.\n";
}
============================================
W swince Kasi bylo: 13.8 zl.
Dodano 10000 $ - aktualne saldo: 10000 $.
Dodano 25000 $ - aktualne saldo: 35000 $.
Dodano 33333 $ - aktualne saldo: 68333 $.
Saldo konta na Kajmanach: 68333 $.
Przyjazń w wypadku szablonu klas
" klasy szablonowe mogą mieć przyjaciół (funkcje i klasy
zaprzyjaznione)
" mo\liwe dwie sytuacje:
o wszystkie klasy wyprodukowane z szablonu będą
miały wspólnego, identycznego przyjaciela (funkcję lub
klasę)  deklaracja funkcji (klasy) zaprzyjaznionej nie
zale\y od parametrów szablonu klasy
o ka\da z klas szablonowych ma własnego, sobie
właściwego przyjaciela  deklaracja funkcji (klasy)
zaprzyjaznionej zale\y od parametrów szablonu klasy
" problem  chcemy zdefiniować funkcję zaprzyjaznioną
której definicja zale\y od parametru szablonu nie
będącego nazwą typu
o taką funkcję musimy zadać jako szablon funkcji
o ten szablon klasy powinien zale\eć od parametru nie
będącego nazwą typu
o szablon funkcji nie mo\e zale\eć od parametru nie
będącego nazwą typu  sprzeczność
" wyjście z problemu
o dokonujemy definicji funkcji zaprzyjaznionej w ciele
definicji szablonu
o wtedy jesteśmy w zasięgu leksykalnym szablonu klasy
 parametry szablonu klas są zdefiniowane  mo\na
ich
Przykład:
#include
class zespol {
float re, im;
public:
zespol(float r=0, float i=0) : re(r), im(i) { }
friend ostream & operator<<(ostream &o, const zespol &z);
};
ostream & operator<<(ostream &o, const zespol &z)
{
o << "[" << z.re << "," << z.im << "] ";
return o;
}
template
class tabela {
A tab[max];
public:
void wsadz(A a, int nr) {tab[nr]=a;}
A wyjmij(int nr) {return tab[nr];}
friend ostream & operator<<(ostream &o, const tabela &tt)
{
for(int i=0; i o << tt.tab[i] << " ";
return o;
}
};
main()
{
tabela s;
s.wsadz("Ala",0);
s.wsadz("kota",2);
s.wsadz("ma",1);
cout << "Tabela s zawiera napis: " << s << endl;
zespol z1(3.0,2);
zespol z2(1.2,-3.3);
tabela t;
t.wsadz(z1,0);
t.wsadz(z2,1);
cout << "Tabela t zawiera liczby: " << t << endl;
}
==========================================
Tabela s zawiera napis: Ala ma kota
Tabela t zawiera liczby: [3,2] [1.2,-3.3]
Szablony klas a dziedziczenie
" klasy szablonowe (powstałe z jednego szablonu) nie mają
z sobą nic wspólnego  inaczej ni\ klasy powiązane
relacją dziedziczenia
" klasy szablonowe są takimi samymi klasami jak inne 
mogą być u\yte w dziedziczeniu (być klasami
podstawowymi i pochodnymi)
" mo\liwe są następujące przypadki:
o zwykła klasa mo\e dziedziczyć klasę szablonową
o specjalizowana klasa szablonowa mo\e dziedziczyć
zwykłą klasę lub klasę szablonową
o szablon klasy mo\e dziedziczyć zwykłą klasę,
specjalizowaną klasę szablonową lub inny szablon
Przykłady dziedziczenia:
1. zwykła klasa, która dziedziczy po klasie szablonowej
2. szablon, który dziedziczy po innym szablonie
Ad.1
#include
template
class schowek {
A zawartosc;
public:
schowek(A a) : zawartosc(a){ }
void wsadz(A a) {zawartosc=a;}
A wyjmij() {return zawartosc;}
};
class portfel : public schowek {
const int rozmiar;
public:
portfel(int wielkosc) : rozmiar(wielkosc), schowek(0.0) { }
void raport()
{
if (rozmiar<15) cout << "W malym portfelu jest ";
else cout << "W duzym portfelu jest ";
cout << wyjmij() << " zl." << endl;
}
};
main()
{
portfel czarny(12);
czarny.wsadz(czarny.wyjmij()+100.0);
czarny.wsadz(czarny.wyjmij()-2.5);
portfel brazowy(16);
brazowy.wsadz(brazowy.wyjmij()+1000.0);
brazowy.wsadz(brazowy.wyjmij()-250.38);
czarny.raport();
brazowy.raport();
}
==========================================
W malym portfelu jest 97.5 zl.
W duzym portfelu jest 749.62 zl.
" klasa zwykła portfel dziedziczy po klasie szablonowej
schowek
" rozszerzenia:
o dodanie składowej rozmiar
o dodanie metody raport
Ad.2
#include
#include
template
class schowek {
A zawartosc;
public:
schowek(A a) : zawartosc(a){}
void wsadz(A a) {zawartosc=a;}
A wyjmij() {return zawartosc;}
};
template
class b_schowek : public schowek {
char * PIN;
public:
b_schowek(B suma, char * h) : PIN(h), schowek(suma) {}
B wyjmij(char* haslo = "")
{
if(!strcmp(PIN,haslo))
return schowek::wyjmij();
else return 0;
}
};
char* b_schowek::wyjmij(char* haslo)
{
if(!strcmp(PIN,haslo))
return schowek::wyjmij();
else return "";
}
main()
{
b_schowek sejf(10000.0,"1357");
cout << "Pytam bez PIN-u : " << sejf.wyjmij() << endl;
cout << "Pytam - zly PIN : " << sejf.wyjmij("2383") << endl;
cout << "Pytam - PIN O.K.: " << sejf.wyjmij("1357") << endl;
cout <<
"+++++++++++++++++++++++++++++++++++++++++++++++++++\n";
b_schowek odzew("Zuzanna lubi je tylko jesienia",
"Najlepsze kasztany sa na Placu Pigalle");
cout << "Bez hasla : \n" << "Odzew : " << odzew.wyjmij() << endl;
cout << "Zle haslo : Abrakadabra\n" << "Odzew : "
<< odzew.wyjmij("Abrakadabra") << endl;
cout << "Dobre haslo : Najlepsze kasztany sa na Placu Pigalle\n"
<< "Odzew : "
<< odzew.wyjmij("Najlepsze kasztany sa na Placu Pigalle")
<< endl;
}
==========================================
Pytam bez PIN-u : 0
Pytam - zly PIN : 0
Pytam - PIN O.K.: 10000
+++++++++++++++++++++++++++++++++++++++++++++++++++
Bez hasla :
Odzew :
Zle haslo : Abrakadabra
Odzew :
Dobre haslo : Najlepsze kasztany sa na Placu Pigalle
Odzew : Zuzanna lubi je tylko jesienia
" szablon b_schowek dziedziczy po szablonie schowek
" oba szablony parametryzowane tym samym parametrem
(nazwą typu)
" rozszerzenia:
o dodatkowe pole PIN
o modyfikacji metody wyjmij (by uwzględniała czy
podane hasło zgadza się z zawartością pola PIN
" dla szablonu b_schowek określamy specjalizowaną
metodę klasy


Wyszukiwarka

Podobne podstrony:
09 szablony klas
9 szablonAI
Konkurs czytelniczy dla klas pierwszych
szablon (tekst obok obrazka)b
Szablony na rozmĂłwki chomikowe
html, css szablon
Test1 dla klas 5 6 z poprawna polszczyzną na codzień(1)
20 Kod ramki szablon
Diagramy klas

więcej podobnych podstron