1 / 41

Objektno orijentisano programiranje

Objektno orijentisano programiranje. Preklapanje operatora. Preklapanje operatora. Pojam preklapanja operatora Operatorske funkcije Funkcije članice i globalne funkcije Bočni efekti i veze između operatora Unarni i binarni operatori Izbor povratnih vrijednosti operatorskih funkcija.

fionn
Download Presentation

Objektno orijentisano programiranje

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Objektnoorijentisano programiranje Preklapanje operatora

  2. Preklapanje operatora • Pojam preklapanja operatora • Operatorske funkcije • Funkcije članice i globalne funkcije • Bočni efekti i veze između operatora • Unarni i binarni operatori • Izbor povratnih vrijednosti operatorskih funkcija

  3. Pojam preklapanja operatora • Preklapanje operatora (operator overloading) • predstavlja redefinisanje postojećih operatora zbog potrebe da na specifičan način rade sa novim tipovima podataka (npr. klasnim tipovima) • omogućava da se ugrađeni C++ operatori prilagode tako da izvršavaju određenu akciju nad objektima klasnih tipova

  4. Pojam preklapanja operatora (nastavak) • Moguće je izvršiti preklapanje skoro svih operatora u jeziku C++ • Zavisno od konteksta u kome je upotrijebljen operator generiše se odgovarajući kod pri prevođenju programa • Koncept preklapanja operatora treba pažljivo koristiti, zbog mogućih neželjenih efekata • Primjeri korištenja preklapanja operatora • operator dodjele se koristi na isti način za različite tipove podataka • operator sabiranja se koristi i za cijele i za realne brojeve

  5. Pojam preklapanja operatora (nastavak) • Za korištenje operatora nad objektima klasnih tipova potrebno je preklapanje operatora, osim u dva slučaja: • operator dodjele = se može koristiti i bez redefinisanja, a može se i eksplicitno redefinisati • adresni operator & se može koristiti i bez redefinisanja, a može se i eksplicitno redefinisati • Preklapanje se vrši tako što se definiše operatorska funkcija • Operatorske funkcije se implementiraju kao metode ili kao globalne funkcije (obično prijateljske funkcije klasa)

  6. Pojam preklapanja operatora (primjer) • Pretpostavimo da su u programu potrebni kompleksni brojevi i operacije nad njima. • Tip kompleksnog broja će realizovati klasa koja sadrži elemente (real, imag), a takođe i funkcije za operacije. • Pogodno je da se pozivi funkcija koje realizuju operacije mogu notacijski predstaviti standardnim operatorima. • U jeziku C++, operatori za korisničke tipove (klase) su specijalne operatorske funkcije. • Operatorske funkcije nose ime operator@, gde je @ neki operator ugrađen u jezik. • Operatorske funkcije preklapaju standaradne operatore (+, -, *, /, ...).

  7. Primjer

  8. Operatorske funkcije • Operatorske funkcije se mogu koristiti u izrazima kao i operatori nad ugrađenim tipovima. • Ako je operatorska funkcija definisana na prethodno opisan način, izraz t1@t2 se tumači kao operator@(t1,t2):

  9. Osnovna pravila preklapanja operatora • C++ dozvoljava preklapanje operatora kao što dozvoljava i preklapanje imena funkcija. • Princip preklapanja omogućava da se definišu nova značenja operatora za korisničke tipove.

  10. Osnovna pravila preklapanja operatora (nastavak) • Postoje neka ograničenja u preklapanju operatora: • ne mogu da se preklope operatori ., .*, ::, ?: i sizeof, dok svi ostali mogu; • ne mogu da se redefinišu značenja operatora za primitivne (standardne) tipove podataka; • ne mogu da se uvode novi simboli za operatore; • ne mogu da se mijenjaju osobine operatora koje su ugrađene u jezik: n-arnost, prioritet i asocijativnost.

  11. Operatorske funkcije – pravila • Operatorske funkcije mogu biti: • funkcije članice klase kod kojih je skriveni argument lijevi operand ili • globalne funkcije (uglavnom prijatelji klasa) kod kojih je bar jedan argument tipa korisničke klase. • Za korisničke tipove su unaprijed definisana tri operatora: = (dodela vrednosti), & (uzimanje adrese) i , (lančanje). • Sve dok ih korisnik ne redefiniše, oni imaju podrazumijevano značenje.

  12. Operatorske funkcije – pravila (nastavak) • Podrazumijevano značenje operatora = je kopiranje objekta član po član. • Pri kopiranju članova tipa klase, pozivaju se operatori = klasa kojima članovi pripadaju. • Ako je član objekta pokazivač, kopiraće se samo taj pokazivač, a ne i pokazivana vrijednost. • Kada treba kopirati i objekat na koji ukazuje član-pokazivač korisnik tada treba da redefiniše operator =. • Vrijednosti operatorskih funkcija mogu da budu bilo kog tipa, pa i void. • Ako se simbol operatora sastoji od slova (npr. new), mora se pisati odvojeno od ključne riječi operator.

  13. Bočni efekti i veze između operatora • Bočni efekti koji postoje kod operatora za ugrađene tipove nikad se ne podrazumijevaju za redefinisane operatore. • To važi za operatore ++ i -- (prefiksne i postfiksne) i sve operatore dodjele (=, +=, -=, *= itd.). • Operator = (i ostali operatori dodjele) ne mora da mijenja stanje objekta; ipak, ovakve upotrebe treba izbjegavati. • Strogo se preporučuje da operatori koje definiše korisnik imaju očekivano značenje, radi čitljivosti programa. • Npr. ako su definisani i operator += i operator +, dobro je da a+=b ima isti efekat kao i a=a+b.

  14. Bočni efekti i veze između operatora (nastavak) • Veze koje postoje između operatora za ugrađene tipove se ne podrazumijevaju za redefinisane operatore. • Npr, ako je definisan operator +, a+=b ne znači automatski a=a+b, (+= mora posebno da se definiše). • Kada se definišu operatori za klasu, treba težiti da njihov skup bude kompletan. • Npr, ako su definisani operatori = i +, treba definisati i operator +=; ili, za == treba definisati i !=.

  15. Operatorske funkcije kao članice ili kao globalne funkcije • Ako je @ neki binarni operator (npr +), on može da se realizuje: • Kao funkcija članica klase X (mogu se argumenti prenositi i po referenci) • Kao prijateljska globalna funkcija • Nije dozvoljeno da se u programu nalaze obje ove funkcije.

  16. Operatorske funkcije kao članice <tip> operator@ (X) Poziv a@b se sada tumači kao: a.operator@(b) , za funkciju članicu

  17. Operatorske funkcije kao prijateljske funkcije <tip> operator@ (X,X) Poziv a@b se sada tumači kao: operator@(a,b) , zaglobalnu funkciju

  18. Primjer

  19. Operatorske funkcije kao funkcije članice ili prijateljske funkcije • Kod operatorske funkcije članice klase lijevi operand je skriveni argument – objekat date klase. • Ako lijevi operand treba da bude standardnog tipa mora se definisati prijateljska funkcija u klasi drugog argumenta. • Primjer: complex operator-(double d, complex c) mora biti prijateljska, a ne članica. • Operatorska funkcija članica ne dozvoljava konverziju lijevog operanda.

  20. Unarni i binarni operatori • Unarni operator ima samo jedan operand, pa se može realizovati: • kao operatorska funkcija članica bez argumenata: tip operator@ () • kao globalna funkcija sa jednim argumentom: tip operator@ (X x) • Binarni operator ima dva argumenta, pa se može realizovati: • kao funkcija članica sa jednim argumentom: tip operator@ (X xdesni) • kao globalna funkcija sa dva argumenta: tip operator@ (X xlevi, X xdesni)

  21. Preklapanje unarnih operatora • Unarni operator može biti preklopljen kao: • nestatička funkcija članica bez argumenata; ne može biti statička jer mora pristupati pojedinačnom atributu • samostalna funkcija (nije funkcija članica) sa jednim argumentom (objekat ili referenca)

  22. Preklapanje binarnih operatora • Binarni operator može biti preklopljen kao: • nestatička funkcija članica sa jednim argumentom • samostalna funkcija sa dva argumenta (bar jedan mora biti objekat ili referenca na objekat)

  23. Primjer

  24. Izbor povratnih tipova operatorskih funkcija • operatori koji mijenjaju lijevi operand (npr. =) treba da vrate referencu na lijevi operand • operatori koji biraju ili isporučuju operande (npr. [], ->, ()) obično treba da vrate referencu na izabranu vrednost • operatori koji izračunavaju novu vrijednost, a ne mijenjaju svoje operande (operatori nad bitovima, +, -, *, /, %, &, \, ^, &&, ||, unarni (-, +), !~) obično treba da vrate kopiju lokalno kreiranog objekta • preinkrement i predekrement - obično treba da vrate referencu na operand • postinkrement i postdekrement - obično treba da sačuvaju kopiju svog operanda, izmijene operand i zatim vrate kopiju

  25. Preklapanje operatora ++ i -- • Operatori inkrementiranja i dekrementiranja imaju: • prefiksni oblik: ++objekat --objekat • postfiksni oblik: objekat++ objekat-- • Da bi se omogućilo preklapanje operatora ++ za oba oblika, moramo imatirazličite definicije operatorskih funkcija za prefiksno odnosno postfiksno inkrementiranje.

  26. Primjer1 #include <iostream.h> class Complex { double real, imag; public: friend ostream & operator<< (ostream &dat, const Complex &z) { return dat << "(" << z.real << "," << z.imag << ")" ; } Complex (double re=0, double im=0) : real(re), imag(im) {} Complex & operator++ () { ++real; return *this; } Complex operator++ (int i) { Complex t=*this; real++; return t; } Complex & operator-- () { --real; return *this; } Complex operator-- (int i) { Complex t=*this; real--; return t; } };

  27. Primjer2 #include <iostream.h> class Complex { double real, imag; public: friend ostream & operator<< (ostream &dat, const Complex &z) { return dat << "(" << z.real << "," << z.imag << ")" ; } Complex (double re=0, double im=0) : real(re), imag(im) {} friend Complex & operator++ ( Complex &z) { z.real++; return z; } friend Complex operator++ ( Complex &z, int i) { Complex t=z; z.real++; return t; } friend Complex & operator-- ( Complex &z) { z.real--; return z; } friend Complex operator-- ( Complex &z, int i) { Complex t=z; z.real--; return t; } };

  28. Preklapanje operatora << i >> • U C++ ne postoje naredbe niti operatori za ulaz i izlaz podataka, već se ulaz i izlaz realizujuodgovarajućim klasama. • Svakoj otvorenoj datoteci, kao i standardnom ulazu/izlazu pridružuje se po primjerak jedne odtih klasa. • Pristup nekoj datoteci ostvaruje se pristupanjem tim objektima putem njihovihfunkcija članica ili prijateljskih funkcija. • Sve potrebne deklaracije vezane za klase za ulaz i izlaz podataka nalaze se u <iostream.h> • Klasa za ulaz podataka naziva se istream. Klasa za izlaz podataka naziva se ostream.

  29. Preklapanje operatora << i >> • Objekat klase istream za pristup standardnom ulazu (tastaturi) zove se cin. • Objekat klase ostream za pristup standardnom izlazu (monitor) zove se cout. • Ova dva objekta (cin, cout) automatski se stvaraju na početku izvršavanja svakog programa. • Operatori za čitanje i pisanje podataka (uz primjenu ulazno-izlaznih konverzija) definisani su zasve standardne tipove podataka preklapanjem operatora >> i <<.

  30. Preklapanje operatora << i >> • Prototipovi odgovarajućih operatorskih funkcija su: • istream & operator>> (istream &dat, Tip &data); • ostream & operator<< (ostream &dat, const Tip &data); • Obje funkcije vraćaju upućivač na dat (cin i cout). • Ovi upućivači su ujedno iprvi operandi operatorskih funkcija. • Ovo omogućava kaskadno pozivanje operatora>> i <<, odnosno prenošenje više podataka jednim izrazom. Ovo je moguće jer je njihovaasocijativnost slijeva udesno.

  31. Preklapanje operatora << i >> • Programer može preklapanjem operatora >> i << da obezbijedi operatore za U/I konverzijesvojih klasa. • Ove funkcije moraju da budu prijateljske funkcije korisničkim klasama. • Ne moguda budu funkcije članice, jer prvi objekat nije korisnički definisan.

  32. Primjer #include <iostream.h> class Complex { double real, imag; friend ostream & operator<< (ostream &dat, const Complex &z) { return dat << "(" << z.real << "," << z.imag << ")" ; } public: Complex (double re=0, double im=0) : real(re), imag(im) {} }; main() { Complex z(1,1); cout << "z = " << z << endl; }

  33. Preklapanje operatora za konverziju tipa (tip) • Konverzija podataka iz jednog tipa u neki drugi tip u slučajevima • dodjele vrijednosti • računanja pri različitim tipovima operanada • prenošenja vrijednosti u funkciju • vraćanja vrijednosti iz funkcije • Kompajler zna kako se vrše konverzije između standardnih tipova (konverzije ugrađene u sam jezik) • Operacija konverzije obično se nazivakastovanje (cast).

  34. Preklapanje operatora za konverziju tipa (tip) • Kod korisnički definisanih podataka kompajler ne zna kako se vrše konverzije, pa programer mora to posebno da definiše. • Moguće realizacije: • pomoću konstruktora konverzije - konstruktor sa jednim argumentom određenog tipakoji prilikom kreiranja objekta vrši konverziju argumenta. • pomoću operatora konverzije (cast operator), mora biti nestatička funkcijačlanica.

  35. Preklapanje operatora za konverziju tipa (tip) • Operatorska funkcija, koja vrši konverziju u tip (klasu) T, ima oblik • operator T() • ne navodi se tip koji vraća, jer se podrazumijeva da je to upravotip u koji treba biti konvertovan objekat.

  36. Primjer class Kompl { double re, im; public: Kompl (double r=0, double i=0) { re=r; im=i; } // Inicijalizacija ili konverzija. operator double(){ return sqrt(re*re+im*im); } // Konverzija u double. friend double real (Kompl z) { return z.re; } // Realni dio. friend double imag (Kompl z) { return z.im; } // Imaginarni dio. Kompl operator+ (Kompl z) // Sabiranje. { z.re += re; z.im += im; return z; } friend ostream& operator<< (ostream& it, const Kompl& z) { return it << '(' << z.re << ',' << z.im << ')'; } }; int main () { Kompl a (1, 2); cout << "a = " << a << endl; Kompl b = a; cout << "b = " << b << endl; Kompl c = 5; cout << "c = " << c << endl; cout << "a+b = " << a + b << endl; cout << "a+3 = " << a + (Kompl)3 << endl; cout << "|a|+3 = " << (double)a + 3 << endl; cout << "a+(3,4) = " << a + Kompl (3,4) << endl; cout << "dble(a) = " << (double)a << endl; double d=Kompl(3,4); cout << "d = " << d << endl; }

  37. Preklapanje operatora = • Ovaj operator ima automatsko tumačenje za objekte klasnih tipova, kopiranje izvorišnog u odredišni objekat, polje po polje • Ovakvo ponašanje je zadovoljavajuće samo za jednostavne objekte • Kod složenih objekata potrebno je izvršiti preklapanje operatora = da bi se izvršilo kopiranje kompletnog objekta • Operator = može biti preklopljen samo nestatičkim metodama klasa, ne može biti globalna funkcija izvan klase

  38. Primjer class Tekst { char* txt; // Pokazivac na sam tekst. public: Tekst (const char* niz) { // Konverzija iz char* u Tekst. txt = new char [strlen(niz)+1]; strcpy (txt, niz); } Tekst (const Tekst& tks) { // Inicijalizacija Tekst-om. txt = new char [strlen(tks.txt)+1]; strcpy (txt, tks.txt); } Tekst& operator= (const Tekst& tks) { // Dodela vrednosti. if (this != &tks) { delete [] txt; txt = new char [strlen(tks.txt)+1]; strcpy (txt, tks.txt); } return *this; } ~Tekst () { delete [] txt; } }; int main () { Tekst a ("Dobar dan."); // Stvaranje i inicijalizacija. Tekst b = Tekst ("Zdravo."); Tekst c (a), d = b; a = b; // Dodela vrednosti. }

  39. Preklapanje operatoraza indeksiranje [] • Binarni operator, odgovara mu operatorska funkcija • tip_rezultataoperator[] (indeks) • Pristup elementu niza niz[ind] odgovara izrazu • niz.operator[] (ind) • Preklapanje operatora [] u nekoj klasi omogućava korišćenje objekata izrazima oblika • obj[ind] • Za razliku od standardnog indeksiranja (indeksni izraz je cjelobrojan), kod preklopljenog operatora [] tip argumenta ind može da bude bilo kojeg tipa.

  40. Preklapanje operatoraza indeksiranje [] • Moguće primjene kod objektnih nizova kod kojih se elementima (objektima) ne pristupa na bazirednog broja (indeksa) nego na bazi neke vrijednosti (ključa). • Da bi izraz sa preklopljenim operatorom [] mogao da se koristi u izrazima oblika obj[ind]=izraz, tip vrijednosti operatorske funkcije operator[] () mora biti upućivač na objekte posmatrane klase. • Operatorska funkcija djeluje samo na objekat svoje klase, a ne na nizobjekata. • Za preklapanje operatora indeksiranja mogu da se koriste samo nestatičke metode.

  41. Preklapanje operatora za pozivanje funkcija() • Binarni operator, odgovara mu operatorska funkcija • tip_rezultataoperator() (arg1, arg2, ..., argN) • Pozivanje funkcije f(arg1, arg2, ... , argN) odgovara izrazu • f.operator() (arg1, arg2, ... , argN) • Preklapanje operatora () u nekoj klasi omogućava korišćenje objekata izrazima oblika • obj(arg1, arg2, ... , argN) • Preklapanje samo nestatičkim metodama

More Related