OOP Templejti

Preview:

DESCRIPTION

Elektronski fakultet

Citation preview

Objektno-orijentisano programiranje

Šabloni (Templates)

Kako smo došli u situaciju da nam šabloni uopšte trebaju? Recimo da je potrebno da napišemo funkciju koja će

određuje koji je od data dva podatka veći. Ukoliko se radi o celobrojnim podacima, funkcija bi izgledala:

int max (int i, int j){ return i>j ? i : j;}

Međutim, šta ako umesto celih imamo realne brojeve? Onda bi funkcija izgledala ovako:

float max (float i, float j){ return i>j ? i : j;}

Razlike između ove dve funkcije se svode na sistematsko zamenjivanje oznake tipa unutar cele definicije fukcije. To je rutinski posao i on se može automatizovati korišćenjem šablonskih ili generičkih funkcija.

Primer generičke funkcije za gornji primer bi bio:

template <class T>T max (T i, T j){ return i>j ? i : j;}

Srećom, u jeziku C++ postoji ugrađeni mehanizam za šablone

Šablonske (generičke) funkcije Prvi red u kodu sa prethodnog slajda:

template <class T>

definiše klasu T kao formalni argument koji će biti zamenjen stvarnim argumentom u trenutku korišćenja šablona. Na primer, ukoliko se pozove max(5,8), T će biti tip int.

Funkcije ili klase opisane pomoću šablona nazivaju se generičke funkcije ili generičke klase. Na osnovu njih se kasnije generišu konkretne funkcije ili klase.

Kako izgledaju i čemu služe šablonske funkcije i klase Opšti oblik za šablone funkcija ili klasa je:

template < argument, argument, ... > opis

Argumenti mogu da označavaju tipove ili konstante. Opšti oblik argumenata je:

class identifikator_tipa (npr. class T)ilioznaka_tipa identifikator_konstante (npr. int k)

Opis može da bude deklaracija (prototip) ili definicija generičke funkcije (odnosno klase) čiji se šablon opisuje.

Šabloni mogu značajno da povećaju fleksibilnost i da smanje veličinu koda.

Generisanje funkcija Funkcije na osnovu zadatog šablona se generišu:

automatski - kad se naiđe na poziv generičke f-je sa stvarnim argumentima koji mogu da se uklope u šablon bez konverzije tipova argumenata.

na zahtev programera - navođenjem deklaracije (prototipa) za datu generičku f-ju sa željenim argumentima.

Zaobilaženje generisanja funkcija na osnovu šablona postiže se navođenjem definicije odgovarajuće obične funkcije koju prevodilac mora da nađe pre nego što izvrši generisanje na osnovu šablona.

Primer:float max (float, float); // eksplicitni zahtev za generisanjefloat g = max (i, f);max<float>(i, f);

Primer 1.template <class Type>Type min (Type a, Type b){

return a < b ? a : b;}

int main(){

// ok: min(int, int)min(10, 20);

// ok: min(double, double)min(10.0, 20.0);

return 0;}

Napomena: Naziv parametra šablonske funkcije NE MORA da bude Type. Ispravno će raditi i ovakava funkcija:template <class Cvet >Cvet min (Cvet a, Cvet b){

return a < b ? a : b;}

Tipski i netipski parametri šablona Tipski parametri se navode kao instanca neke

nedeklarisane klase (kao na primer class Cvet)

Kada dođe do pravljenja primeraka šablona, tipski parametri (kao onaj class Cvet) zamenjuju se stvarnim tipovima podataka – bilo ugrađenim (int, double, char*) ili korisnički definisanim (transport, vector <int>*)

Netipski parametar šablona sadrži uobičajenu deklaraciju parametara. Netipski parametar šablona označava potencijalnu vrednost. Ova vrednost predstavlja konstantu u definiciji šablona.

Videti primer na sledećem slajdu.

Tipski i netipski parametri šablona - primer Ovde je class Cvet tipski, a int velicina netipski

parametar, odnosno konstantna vrednost koja postavlja veličinu niza:

template <class Cvet, int velicina>

Kada dođe do pravljenja primeraka šablona funkcije min, vrednost size zameniće se konstantnom vrednošću u vreme kompajliranja.

Cvet min(Cvet niz[velicina])

Šablonska funkcija min – ceo kodtemplate <class Cvet, int velicina>Cvet min(const Cvet niz[velicina]){/* Parametrizovana funkcija za pronalaženje minimalne

vrednosti u nizu */

Cvet minvrednost = niz[0];for(int i = 1; i < velicina; i++){

if(niz[i] < minvrednost)minvrednost = niz[i];

}

return minvrednost;}

Napomene Objekat ili tip koji su deklarisani u definiciji šablona funkcije ne

mogu nositi isti naziv kao i parametar šablona.

template <class Type>Type min (Type a, Type b){

// Pogrešno! Redefinicija šablonskog parametra.typedef double Type;

Type tmp = a < b ? a : b;return tmp;

}

Naziv tipskog parametra se može koristiti za određivanje tipa rezultata u šablonu funkcije:

template <class Type, class T2, class T3>Type min (T2 a, T3 b)

Napomene Naziv parametra šablona se može koristiti samo jednom u istoj

listi parametara u šablonu. Dakle, sledeći kod je neispravan:

template <class Type, class Type>Type min (Type a, Type b)

Međutim naziv parametra šablona može se ponovo koristiti u deklaracijama ili definicijama drugih šablona. Dakle, sledeći kod je ispravan:

template <class Type>Type min (Type a, Type b)

template <class Type>Type max (Type a, Type b)

Šabloni klasa Šablon klase je “uputstvo” za formiranje klase pri čemu su jedan ili

više tipova ili vrednosti parametrizovani. Pretpostavimo da želimo da definišemo klasu koja podržava

mehanizam rada sa redom čekanja (engleski Queue). Red čekanja je FIFO struktura.

Nazovimo našu klasu Queue i neka podržava sledeće operacije: proveravanje da li je red pun

bool is_full() proveravanje da li je red prazan

bool is_empty() dodavanje elementa u red

void add(item) izbacivanje elementa iz reda

item remove()

Šabloni klasa - dalje Definicija klase Queue tada može da izgleda ovako

class Queue{public:

Queue();~ Queue();

int remove();void add(const int &newItem );bool is_empty();bool is_full();

}

Postavlja se pitanje šta da radimo ako hoćemo da elementi reda budu drugog tipa, a ne integer?

U tom slučaju učinićemo našu klasu templejtskom.

Šablonska klasa Queuetemplate <class Type>class Queue{public:Queue();~ Queue();

Type remove();void add(const Type &newItem);bool is_empty();bool is_full();}

Generisanje raznih klasa Queue na osnovu šablona Da biste generisali razne klase Queue koje sadrže cele

brojeve, kompleksne brojeve i nizove znakova, treba napisati:

Queue <integer> qi;Queue <string> qs;Queue < Complex <double> > qcd;

Ovde je jedino neophodno da postoji prethodno definisana templejtska klasa complex

Templejtske klase, kao i templejtske funkcije, mogu da sadrže i tipske i netipske parametre

Sve napomene koje su date kod šablonskih funkcija važe i za templejtske klase

Primer još jedne šablonske klase Deklaracija klase (Vektor.h)

template <class T, int k>class Vektor {

T element [k];

public:Vektor();T& operator[] (int i);

};

Definicija članova klase (Vektor.h)

template <class T, int k>Vektor<T, k>::Vektor (){

}

template <class T, int k>T& Vektor<T, k>::operator[] (int i) {

if(i < k)return element[i];

return 0;}

Zadatak 7. Napisati templejtsku klasu koja modelira niz sačinjen od

elemenata proizvoljnog tipa. Kao privatne podatke ova klasa treba da ima niz elemenata proizvoljnog tipa i broj elemenata tog niza. Kao javne, klasa treba da ima sledeće funkcije: Default konstruktor koji zauzima prostor za 10

elemenata i postavlja broj elemenata niza na 10 Konstruktor sa jednim celobrojnim parametrom size, koji

zauzima prostor za size elemenata i broj elemenata niza postavlja na size

Konstruktor za kopiranje Destruktor Operator[] za pristup elementima niza Int GetSize() – metodu koja vraća broj elemenata niza Funkciju za uredjivanje elemenata niza u rastući

redosled

Zadatak 7 – nastavak Takođe, kreirati klasu Animal koja od privatnih podataka ima

vrstu i težinu životinje, a od javnih sledeće metode: Default konstruktor koji težinu životinje na 0, a ime na prayan

string Konstruktor koji inicijaliyuje privatne atribute Destruktor Operator < koji poredi dve životinje po težini Operator = koji jedan objekat klase Animal dodeljuje drugom Operator << koji upisuje ime i težinu životinje u tekstualni tok

podataka. Operator >> koji učitava ime i težinu životinje iz tekstualnog

toka podataka. U glavnom programu kreirati po jedan niz sa elementima

celobrojnog tipa i sa elementima klase Animal, učitati elemente nizova sa standardnog ulaza, urediti nizove i elemente uredjenih nizova prikazati na standatdni izlaz

Zadatak 8.Na programskom jeziku C++ napisati program za odredjivanjepobednika jedne trke u brzom skijanju. U okviru zadatka kreirati:

Klasu Vreme koja sadrži privatne atribute: sat (čija se vrednost nalazi u opsegu 0-24), minut (0-60) i sekund (0-60), i javne metode: konstruktor bez argumenata konstruktor koji sve atribute postavlja na zadate vrednosti, operatorsku funkciju - za oduzimanje dva vremena, operatorsku funkciju = za dodelu jednog objekta klase Vreme drugom, operatorsku funkciju < za poredjenje dva vremena.

Definisati i sledeće prijateljske funkcije: operatorsku funkciju >> za učitavanje vremena iz tekstualnog toka

podataka, operatorsku funkciju << za upis vremena u tekstualni tok podataka.

Zadatak 8. Generičku (šablonsku ili templejtsku) klasu Vektor čiji su privatni

članovi broj elemenata u vektoru i njegovi elementi zapamćeni u dinamičkoj zoni memorije. Elementi vektora su proizvoljnog tipa. Javni članovi klase su sledeće funkcije: konstruktor koji postavlja veličinu vektora, destruktor, funkcija za učitavanje elemenata sa standardnog ulaza, operatorska funkcija – za oduzimanje dva vektora, operatorska funkcija = za dodelu jednog vektora drugom, funkcija za nalaženje pozicije minimalnog elementa u vektoru, funkcija za prikaz k-tog elemenata na standardni izlaz.

U funkciji main sa standardnog ulaza učitati broj učesnika u trci, vektor startnih vremena i vektor vremena prolazaka kroz cilj. Odrediti razliku ova dva vektora i na standardni izlaz prikazati poziciju minimalnog elementa u rezultujućem vektoru i vrednost tog elementa (tj. startni broj pobednika i vreme za koje je pre[ao stazu).