Professional Documents
Culture Documents
05 - Genericki Mehanizam
05 - Genericki Mehanizam
Banja Luka
Programski jezici 1
GENERIKI MEHANIZAM
Goran Banjac
goran.banjac@etfbl.net
12/24/14
Generiki mehanizam
Sadraj
Generisanje funkcija
Generisanje klasa
abloni i prijatelji
abloni i nasleivanje
STL
ablon predstavlja definiciju klase ili funkcije koja u sebi sadri, kao formalne
argumente, tipove koji e u fazi generisanja konkretne klase ili funkcije biti
zamenjeni konkretnim tipovima.
Na primer, esto je u praksi potreban vei broj funkcija koje se identino ponaaju, ali nad
razliitim tipovima podataka (npr. funkcija za sortiranje). Ovo je mogue realizovati
preklapanjem funkcija. Meutim, programer mora da napie sve te funkcije, za svaki tip po
funkciju - moe da bude naporno i dugotrajno!
Slino je i sa klasama. esto se u praksi definiu klase koje implementiraju iste operacije nad
svojim podacima lanovima, ali su ti podaci razliitih tipova. Npr. klasa Niz treba da se ponaa
isto bez obzira na to da li je re o nizu celih brojeva ili nizu realnih brojeva. Slino je i sa ostalim
kontejnerskim klasama (lista, stek, stablo, ...).
ablon predstavlja definiciju klase ili funkcije koja u sebi sadri, kao formalne
argumente, tipove koji e u fazi generisanja konkretne klase ili funkcije biti
zamenjeni konkretnim tipovima.
Na primer, esto je u praksi potreban vei broj funkcija koje se identino ponaaju, ali nad
razliitim tipovima podataka (npr. funkcija za sortiranje). Ovo je mogue realizovati
preklapanjem funkcija. Meutim, programer mora da napie sve te funkcije, za svaki tip po
funkciju - moe da bude naporno i dugotrajno!
Slino je i sa klasama. esto se u praksi definiu klase koje implementiraju iste operacije nad
svojim podacima lanovima, ali su ti podaci razliitih tipova. Npr. klasa Niz treba da se ponaa
isto bez obzira na to da li je re o nizu celih brojeva ili nizu realnih brojeva. Slino je i sa ostalim
kontejnerskim klasama (lista, stek, stablo, ...).
Generisanje funkcija
GENERISANI KOD
// Sablonska funkcija za int
void funkcija(int x)
{
cout << x;
}
// Sablon funkcije
template <class Tip>
void funkcija(Tip x)
{
cout << x;
}
// glavni program
int main()
{
int i=100; funkcija(i);
double d=5.25; funkcija(d);
return 0;
}
// glavni program
int main()
{
int i=100; funkcija(i);
double d=5.25; funkcija(d);
return 0;
}
Generisanje funkcija
ablon moe da ima vie parametara,
ali svi moraju da budu
tipovi
(ispred svakog se navodi class ili
// ISPRAVNOtypename)!
template <class T>
void funkcija(T data)
{ cout << data; }
// ISPRAVNO
template <class T>
T funkcija(T data)
{ T x(data); return x;
Primer:
#include <iostream>
using namespace std;
template <typename T>
void f1(T i) { cout << i << endl; }
template <typename T>
T f2(int i) { return (T)i; }
// ISPRAVNO
template <class T1, class T2>
void funkcija(T1 x, T2 y)
{ cout << x << y; }
int main()
{
f1(100); f1('A');
f1<int>(200); f1<char>('B');
cout << f2<int>(100) << endl;
cout << f2<char>(100) << endl;
return 0;
}
100
A
200
B
100
d
Generisanje funkcija
Primer:
#include <iostream>
using namespace std;
template <class Tip>
void sort(Tip niz[], int n)
{
int i, j, rb;
Tip tmp;
for (i=0; i<n-1; i++)
{
for (rb=i, j=i+1; j<n; j++)
if (niz[j]<niz[rb]) rb=j;
if (rb!=i)
{
tmp = niz[i];
niz[i] = niz[rb];
niz[rb] = tmp;
}
}
original: 15 3245 3 62
}
sortirano: 3 15 62 3245
original: 12.5 5
sortirano: 5 12.5
Generisanje funkcija
Primer:
#include <iostream>
using namespace std;
template <class Tip>
Tip maks(Tip a, Tip b)
{
cout << "(Sablon
a=";
cout << a << " b=" << b <<") ";
return (a>b) ? a : b;
}
int maks(int a, int b)
{
cout << "(Original a=";
cout << a << " b=" << b <<") ";
return (a>b) ? a : b;
}
int main()
{
int a=100, b=200;
char c='C', d='D';
int m1 = maks(a,b);
cout << "\tm1: " <<
char m2 = maks(c,d); cout << "\tm2: " <<
int m3 = maks(c,d);
cout << "\tm3: " <<
int m4 = maks(a,c);
cout << "\tm4: " <<
return 0;
}
(Original
(Sablon
(Sablon
(Original
m1
m2
m3
m4
<<
<<
<<
<<
endl;
endl;
endl;
endl;
a=100 b=200)
a=C b=D)
a=C b=D)
a=100 b=67)
m1:
m2:
m3:
m4:
200
D
68
100
Generisanje klasa
GENERISANI KOD
// Sablonska klasa za int
class Klasa<int>
{
public: int data;
};
// Sablon klase
template <class Tip>
class Klasa
{
public: Tip data;
};
// glavni program
int main()
{
Klasa<int> i;
i.data=100; cout << i.data;
Klasa<char> c;
c.data=A; cout << c.data;
return 0;
}
// glavni program
int main()
{
Klasa<int> i;
i.data=100; cout << i.data;
Klasa<char> c;
c.data=A; cout << c.data;
return 0;
}
Generisanje klasa
Primer:
#include <iostream>
using namespace std;
template <class T>
class Niz
{
public:
Niz(int nn=1)
{
void set(int ii, T dd) {
void print()
{
~Niz()
{
private:
T *data;
int n;
};
int main()
{
Niz<int> x(5);
for (int i=0; i<5; i++) x.set(i,i);
cout << "x: "; x.print(); cout << endl;
Niz<char> y(10);
for (int i=0; i<100; i++) y.set(i,'A'+i);
cout << "y: "; y.print(); cout << endl;
return 0;
}
x: 0 1 2 3 4
y: A B C D E F G H I J
Generisanje klasa
Primer:
#include <iostream>
using namespace std;
x: 0 1 2 3 4
y: A B C D E F G H I J
implementacija)
#include <iostream>
using namespace std;
template <class T, int N>
class Niz
{ public: Niz();
void dodaj(T dd);
void print();
private: T niz[N]; int n;
};
template <class T, int N>
Niz<T,N>::Niz() { n=-1; }
template <class T, int N>
void Niz<T,N>::dodaj(T dd)
{ if (n<N-1) { n++; niz[n]=dd; }}
template <class T, int N>
void Niz<T,N>::print()
{ for (int i=0; i<=n; i++)
cout << niz[i] << " ";
int main()
{
Niz<int,5> x;
for (int i=0; i<5; i++) x.dodaj(i);
x.print();
return 0;
Punjenje: 1 2 3 4 5
Stek je pun! Ne moze: 6
Praznjenje: 5 4 3 2 1
Ispraznjeno!
abloni i prijatelji
Prijateljstvo moe biti uspostavljeno izmeu ablona
klase i:
1.
2.
abloni i prijatelji
Primer:
#include <iostream>
using namespace std;
template <class T> class X;
void f()
{ cout << "Prijatelj!" << endl; }
template <class T>
void read(X<T> &x)
{ cout << "data? "; cin >> x.data; }
template <class T>
void print(X<T> &x)
{ cout << "data: " << x.data; }
template <class T>
void set(X<T> &x, T dd)
{ x.data = dd; }
template <class T>
T get(X<T> &x)
{ return x.data; }
Alternative za deklaraciju
prijatelja u klasi:
friend T get <T> (X &x)
friend T get <T> (X<T> &x)
friend T get <> (X<T> &x)
Prijatelj!
100
data? 50
data: 50
abloni i prijatelji
Primer:
#include <iostream>
using namespace std;
template <class T> class X;
template <class T>
ostream &operator<<(ostream &out, X<T> &x)
{ return out << x.data << endl; }
template <class T>
class X
{
friend ostream &operator<< <>(ostream &, X &);
friend istream &operator>>(istream &in, X &x)
{ return in >> x.data; }
private:
T data;
};
int main()
{
X<int> x;
cout << "Unesite x: "; cin >> x;
cout << "Uneli ste: " << x;
return 0;
}
Unesite x: 5
Uneli ste: 5
abloni i nasleivanje
ablonska klasa moe da bude osnovna klasa i da se
iz nje izvede neka druga konkretna neablonska
#include <iostream>
klasa.
class SedmicnaTemp : public Red<int,7>
using namespace std;
{
template <class T, int N>
public:
class Red
double prosjecna()
{
{
public:
double d=0;
Red() { n=0; }
for (int i=1; i<=n; i++) d+=data[i];
int dodaj(T dd)
return d/n;
{
}
if (n>=N) return 0;
void print()
data[++n]=dd; return 1;
{
}
cout << "Temperature: ";
Red<int,7>::print();
virtual void print()
cout << "\nProsek: " << prosjecna();
{
}
for (int i=1; i<=n; i++)
};
cout << data[i] << " ";
int main()
}
{
protected: T data[N+1]; int n;
int t[7] = { 14, 12, 17, 6, -2, 0, -1 };
};
SedmicnaTemp temp;
for (int i=0; i<7; i++) temp.dodaj(t[i]);
Temperature: 14 12 17 6 -2 0 -1
Red<int,7> *r=&temp; r->print();
Prosek: 6.57143
return 0;
}
Primer:
abloni i nasleivanje
Primer:
#include <iostream>
#include <cstring>
using namespace std;
class Ime
{ public:
Ime(const char *t) : s(0)
{
if (t != 0)
{
s = new char[strlen(t)+1];
strcpy(s,t);
}
}
~Ime() { delete [] s; }
protected: char *s;
};
BCD = {2}
BCD = {2,0,1,3,4}
int main()
{
Skup<int,5> x("BCD");
x.dodaj(2); x.print();
for (int i=0; i<10; i++)
if (!x.dodaj(i)) break;
x.print();
return 0;
}
abloni i nasleivanje
ablon moe da se izvede
iz drugog ablona.
Primer:
#include <iostream>
using namespace std;
int main()
{
template <class T, int N> class Niz
Red<int,4> x;
{ public:
cout << "Punjenje reda: ";
Niz() { n=-1; }
for (int i=0; i<10; i++)
int dodaj(T dd)
if (x.dodaj(i)) cout << i << " ";
{ if (n>=N-1) return 0;
else
niz[++n]=dd; return 1; }
{ cout << "\nRed je pun!"; break; }
void print()
int data;
{ for (int i=0; i<=n; i++)
while (x.uzmi(data))
cout << niz[i] << " "; }
{
protected: T niz[N]; int n;
cout << "\nPraznjenje: " << data;
};
cout << " Ostalo: "; x.print();
}
template <class T, int N>
return 0;
class Red : public Niz<T,N>
}
{ public:
int uzmi(T &data)
{ if (this->n<0) return 0;
Punjenje reda: 0 1 2 3
data = this->niz[0];
Red je pun!
for (int i=0; i<this->n; i++)
Praznjenje: 0 Ostalo: 1 2 3
this->niz[i]=this->niz[i+1];
Praznjenje: 1 Ostalo: 2 3
this->n--;
return 1;
Praznjenje: 2 Ostalo: 3
}
Praznjenje: 3 Ostalo:
Pristup nasleenim lanovima
};
abloni i nasleivanje
Primer:
#include <iostream>
using namespace std;
template <class T> class Niz
{ public:
Niz() { n=0; data = new T[1]; }
void dodaj(T dd)
{ if (n == 0) data[n++] = dd;
else
{ T *temp = new T[++n];
for (int i=0; i<n-1; i++)
temp[i] = data[i];
temp[n-1]=dd;
delete [] data;
data = temp; }
}
virtual void print()
{
for (int i=0; i<n; i++)
cout << data[i] << " ";
}
~Niz() { delete [] data; }
protected: T *data; int n;
};
Red: 2 4 8 16 32 64
Pocetni: 2
Krajnji: 64
rep
data
next
void print()
{
Cvor *tmp = glava;
if (tmp)
cout << "Lista: ";
while (tmp)
{
cout << tmp->data
<< " ";
tmp = tmp->next;
}
}
public:
Lista() : glava(0), rep(0) {}
~Lista()
Lista& plus(T t)
{
{
while (glava)
if (glava==0)
{
glava = rep = new Cvor(t);
Cvor *tmp =
else
glava->next;
{
delete glava;
rep->next = new Cvor(t);
glava = tmp;
rep = rep->next;
}
}
}
return *this;
};
}
data
next
data
next
int main()
{
Lista<int> li;
for (int i=1; i<5; i++)
li.plus(100+i);
li.print(); cout << endl;
Lista<string> ls;
ls.plus("BL").
plus("BG").
print();
return 0;
}
STL: <vector>
Primer 1: Kreiranje vektora
#include <iostream>
#include <vector>
using namespace std;
template<class T>
void print(const vector<T> &v)
{
for (int i=0; i<v.size(); i++)
cout << v[i] << " ";
cout << endl;
}
#include <iostream>
#include <vector>
#include <string>
using namespace std;
template<class T>
void print(const vector<T> &v)
{
cout << "niz: ";
for (int i=0; i<v.size(); i++)
cout << v[i] << " ";
cout << endl;
}
int main()
{
vector<string> niz;
niz.push_back("BL");
niz.push_back("BG"); print(niz);
niz.insert(niz.begin(),"SK"); print(niz);
niz.insert(niz.begin(),2,"A"); print(niz);
niz.insert(niz.end(),"0"); print(niz);
return 0;
}
int main()
{
vector<int> niz1;
cout << "niz1: " << niz1.size();
cout << " elemenata\n";
vector<double> niz2(5);
cout << "niz2: " << niz2.size();
cout << " elemenata\n";
vector<char> niz3(5, 'A');
cout << "niz3: ";
print(niz3);
return 0;
}
niz1: 0 elemenata
niz2: 5 elemenata
niz3: A A A A A
niz:
niz:
niz:
niz:
BL BG
SK BL BG
A A SK BL BG
A A SK BL BG 0
STL: <vector>
Primer 3: Brisanje elemenata iz vektora
#include <iostream>
#include <vector>
using namespace std;
template<class T>
void print(const vector<T> &v)
{
cout << "Niz: ";
for (int i=0; i<v.size(); i++)
cout << v[i] << " ";
cout << endl;
}
Niz: 10 11 12 13 14 15
Brisanje s kraja: 15
Niz: 10 11 12 13 14
Brisanje s pocetka: 10
Niz: 11 12 13 14
Brisanje prva dva elementa
Niz: 13 14
int main()
{
vector<int> niz;
for (int i=10; i<16; i++)
niz.push_back(i);
print(niz);
cout << "\nBrisanje s kraja: " << niz.back() << endl;
niz.pop_back(); print(niz);
cout << "\nBrisanje s pocetka: " << niz.front() << endl;
niz.erase(niz.begin()); print(niz);
cout << "\nBrisanje prva dva elementa\n";
niz.erase(niz.begin(),niz.begin()+2); print(niz);
return 0;
}
STL: <vector>
Primer 4: Elementarni iteratori
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> niz;
for (int i=10; i<16; i++)
niz.push_back(i);
vector<int>::iterator i;
cout << "Niz: ";
for (i=niz.begin(); i<niz.end(); i++)
cout << *i << " ";
cout << endl;
reverse(niz.begin()+1,niz.end()-1);
cout << "Naopako: ";
for (i=niz.begin(); i<niz.end(); i++)
cout << *i << " ";
cout << endl;
return 0;
}
Niz: 10 11 12 13 14 15
Naopako: 10 14 13 12 11 15
STL: <vector>
Primer 5: U/I iteratori
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
int main()
{
vector<int> niz;
cout << "Unesite podatke: ";
istream_iterator<int> in(cin);
istream_iterator<int> eos; // end-of-stream iterator
while (in!=eos)
{
niz.push_back(*in);
in++;
}
cout << "\nHorizontalni ispis:\n";
ostream_iterator<int> out1(cout," ");
copy(niz.begin(),niz.end(),out1);
cout << "\n\nVertikalni ispis:\n";
ostream_iterator<int> out2(cout,"\n");
copy(niz.begin(),niz.end(),out2);
return 0;
}