Отпремање презентације траје. Молимо да сачекате

Отпремање презентације траје. Молимо да сачекате

Преклапање оператора Операторске функције Неки посебни оператори

Сличне презентације


Презентација на тему: "Преклапање оператора Операторске функције Неки посебни оператори"— Транскрипт презентације:

1 Преклапање оператора Операторске функције Неки посебни оператори
Конверзије типова Основни стандардни УИ токови

2 Операторске функције Значење оператора уграђених у језик може се дефинисати за корисничке типове. Ако је у програму уведено ново значење неког оператора. Каже се да је он преклопљен. Значење оператора за корисничке типове дефинише се операторским функцијама.

3 Операторске функције Операторске функције имају посебна имена облика где оператор уграђен у језик. Иако је експлицитни позив могућ, као и за сваку другу функцију, операторске функције се позивају као и оператори за уграђене типове.

4 Операторске функције Не могу се преклопити следећи оператори:
. .* :: ?: sizeof Могу да се преклопе и унарне и бинарне форме оператора: + - * &

5 Операторске функције Операторска функција мора да буде или чланица неке класе, или да има бар један аргумент типа класе, набрајања, референце на класу или референце на набрајање. inline complex operator+ (complex c, double d) { return complex(c.real+d,c.imag); } // ova je globalna prijateljska funkcija

6 Операторске функције Преклапањем оператора се не може променити приоритет, асоцијативности или арност оператора. Не могу се увести нови оператори који већ не постоје као уграђени. За операторе доделе (=), узимања адресе (&) и секвенце (,) могуће је предефинисати подразумевано значење.

7 Операторске функције Не могу се предефинисати значења оператора за уграђене типове података. complex operator+(double,double); // greska

8 Операторске функције Операторске функције се наслеђују, осим оператора доделе. Операторске функције не могу да имају подразумеване аргументе. Тип повратне вредности преклопљеног оператора може бити било који кориснички или уграђени тип (ово не важи за new, delete и ->).

9 Операторске функције Треба поштовати правило да операторска функција за неки кориснички тип има очекивано понашање у сваком погледу, па и у смислу повратне вредности. Споредни ефекти код оператора за уграђене типове не морају се реализовати и код преклопљених оператора.

10 Операторске функције Операторскa функција може да буде функција чланица или глобална функција (најчешће пријатељ класе).

11 Операторске функције T (Y); // operatorska funkcija clanica; prvi // argument je objekat cija se funkcija // poziva a drugi je Y T (X,Y); // globalna operatorska funkcija

12 Операторске функције У принципу, не постоје разлози који намећу један или други облик. Функције чланице па и операторске не дозвољавају било какву имплицитну конверзију над објектом чија се функција позива. Глобалне функције то дозвољавају.

13 Операторске функције class complex { double real, imag; public: complex(double r=0, double i=0) : real(r), imag(i) {} friend complex operator+(complex c1, complex c2); }; complex operator+(complex c1, complex c2) { return complex(c1.real+c2.real, c1.imag+c2.imag); }

14 Операторске функције void main { complex c=3.14+complex(1.0,-1.0); // poziva se operator+(complex(3.14),complex(1.0,-1.0)) // … }

15 Операторске функције class complex { double real, imag; public: complex(double r=0, double i=0) : real(r), imag(i) {} friend complex operator+(complex) const; }; complex complex::operator+(complex c2) const { return complex(real+c2.real, imag+c2.imag); }

16 Операторске функције void main { complex c=3.14+complex(1.0,-1.0); // greska! // ne vrsi se complex(3.14).operator+(complex(1.0,-1.0)) // … }

17 Операторске функције Неки оператори треба да мењају вредност својих операнада (нпр, +=, -= и сл. мењају вредност левог операнда). То значи да леви операнд треба да буде лвредност. Ово се може реализовати помоћу глобалне пријатељске функције где је први аргумент референца на неконстантни објекат.

18 Операторске функције complex& operator+=(complex &cl, complex cr) { cl.real+=cr.real; cl.imag+=cr.imag; return cl; } void main { complex c; double d=3.14; d+=c; // greska: d nije lvrednost tipa complex pa ne // moze inicijalizovati referencu na nekonstantu // u pozivu operator+=(complex&, complex) c+=d; // u redu: poziva se operator+=(c, complex(d)); // …

19 Операторске функције Природније је да се чињеница да оператор делује на операнд изрази реализацијом операторске функције као чланице. У том случају се операције врши над објектом који представља леви операнд а не над привременим објектом добијеним имплицитном конверзијом.

20 Операторске функције complex& complex::operator+=(complex cr) { real+=cr.real; imag+=cr.imag; return *this; }

21 Операторске функције Можемо закључити да операторе који захтевају лвредност као свој леви операнд треба реализовати као операторске функције чланице. Операторе који то не захтевају треба реализовати као глобалне функције (најчешће пријатељске).

22 Операторске функције Ако нека операторска функција реализује операцију над операндима који припадају двема класама, онда она треба да буде глобална функција (пријатељ обема класама).

23 Операторске функције class vector; class matrix { friend vector operator* (const matrix&, const vector&); // … }; class vector {

24 Операторске функције vector operator* (const matrix &m, const vector &v) { // mnozenje matrice vektorom }

25 Операторске функције Неки оператори могу да буду и унарни и бинарни (унарни и бинарни -, унарни & узимање адресе и бинарни & - логичко И по битовима,...). Како се они разликују?

26 Операторске функције Унарни префиксни оператор може да се декларише као нестатичка функција чланица без аргумената или као функција нечланица која има један аргумент. Бинарни оператор се може декларисати као нестатичка функција чланица са једним аргументом или као функција нечланица која има два аргумента.

27 Операторске функције class complex { double real, imag; public: complex (double r=0, double i=0) : real(r), imag(i) {} friend complex operator+(complex, complex); complex operator! () const // unarni operator { return complex(real, -imag); } //… };

28 Неки посебни оператори
Оператори инкрементирања (++) и декрементирања (--) имају своје префиксне и постфиксне облике који могу да се разликују за преклопљене операторе. Могу се преклапати и оператори позива функције (()), индексирања низа ([]) и дереференцирања показивача (->).

29 Неки посебни оператори
Од значаја су и оператори креирања и укидања динамичких објеката (new и delete) и оператор доделе (=).

30 Неки посебни оператори
Операторска функција operator++ која прихвата један операнд дефинише префиксни оператор инкрементирања за објекте неке класе. Операторска функција operator++ која прихвата два операнд дефинише постфиксни оператор инкрементирања за објекте неке класе.

31 Неки посебни оператори
Други операнд код постфиксног оператор мора да буде типа int. При позиву, други стварни аргумент ће бити нула.

32 Неки посебни оператори
class X { // … public: X operator++(); // prefiksni operator++ X operator++(int); // postfiksni operator++ };

33 Неки посебни оператори
void main() { X x; ++x; // poziv x.operator++() x++; // poziv x.operator++(0) x.operator++(); // eksplicitni poziv: kao ++x x.operator++(0); // eksplicitni poziv: kao x++ x.operator++(3); // moze i ovo ali ne i x++3 }

34 Неки посебни оператори
Овакве операторске функције могу да буду и функције чланице и глобалне функције. Аналогно је за оператор декрементирања.

35 Неки посебни оператори
Позив функције izraz(lista_izraza) је бинарна операција где је izraz први операнд а lista_izraza други (може бити и празна). Одговарајућа операторска функција је operator().

36 Неки посебни оператори
class X { // … public: int operator() (int,int) {/*…*/} }; void main() { X x1, x2, x3; int i=x1(2,2); // poziv x1.operator() (2,2); i=x2(1,2); // poziv x2.operator() (1,2); i=x3(2,i); // poziv x3.operator() (2,i); }

37 Неки посебни оператори
Нека желимо да направимо класу string која реализује динамичке низове знакова. Ова класа треба да обезбеди конкатенацију, проналажење подниза унутар датог низа и др. Једна од функција би враћала подниз датог низа од места position у дужини length.

38 Неки посебни оператори
string s=“Zdravo!”; string p=s(2,2); // s(2,2) vraca podniz od mesta 2 u // duzini 2, tj. p ce postati “dr” p=p(1,1); // p postaje “d”

39 Неки посебни оператори
class substring; // klasa koja realizuje pojam podniza znakova class string { // klasa koja realizuje niz znakova char *s; // … public: string (const char*); // konstruktor string (const string&); // konstruktor kopije string (const substring&); // konstruktor string& operator=(const string&); // operator dodele string& operator=(const substring&); // operator dodele substring& operator() (int position, int length); // operator () //… };

40 Неки посебни оператори
class substring { // podniz unutar nekog objekta tipa string // … public: substring& operator= (const string&); substring& operator= (const substring&); //… };

41 Неки посебни оператори
Сада може и string s=“Zdravo!”; s(3,1)=“1”;

42 Неки посебни оператори
За објекте који су вишедимензионални низови можемо преклопити оператор () тако да подржава индексирање низа облика x(i,j);

43 Неки посебни оператори
typedef int T; // neki tip T class Matrix { T **m; // sadrzaj matrice int columns, rows; // neki broj kolona i vrsta matrice // … public: Matrix (int m, int n); // konstruktor T& operator() (int i, int j); // operator() };

44 Неки посебни оператори
T& Matrix::operator() (int i, int j) { if ((j>=1)&&(j<=columns)&&(i>=1)&&(i<=rows)) // granice! return m[i-1][j-1]; else error(“Indeksi van granica!”); } Matrix m(13,5); // matrica dimenzija 13x5 m(4,1)=0; // poziv m.operator() (4,1) //… int i=m(3,2); // poziv m.operator() (3,2)

45 Неки посебни оператори
Код повезаних листи нам је обично потребно да имамо показивач на текући елемент листе. Шта више, често нам је потребно више таквих показивача.

46 Неки посебни оператори
typedef int T; // neki tip T class List { struct Elem { // tip elemenata liste T *cont; // pokazivac na sadrzaj elementa liste Elem *next; // pokazivac na sledeci element liste Elem() : cont(0), next(0) {}; // konstruktor Elem(T *t) : cont(t), next(0) {}; // konstruktor Elem(T *t, Elem *prev) : cont(t), next(0) { prev->next=this;} // konstruktor };

47 Неки посебни оператори
Elem *head; // pokazivac na prvi element liste Elem *tail; // pokazivac na poslednji elemen liste // … friend class ListIterator; public: List() : head(0), tail(0) {} ~List(); void put(T &t) { tail=new Elem(&t,tail); }// stavlja u listu T& get(); // uzima iz liste };

48 Неки посебни оператори
class ListIterator { List &lst; // referenca na listu ciji je ovo iterator List::Elem *cur; // pokazivac na tekuci element liste // … public: ListIterator(List &l) : lst(l), cur(l.head) {}; T& operator() (int n); // pomeranje za n mesta unapred T& operator() () // pomeranje za 1 mesto unapred { return operator() (1);} };

49 Неки посебни оператори
T& ListIterator::operator() (int n) { T &temp=*cur->cont; while ((n-- > 0) && cur) cur=cur->next; return temp; }

50 Неки посебни оператори
Oвим је омогућено да за сваку листу имамо више итератора.

51 Неки посебни оператори
List x; int a[10]={1,2,3,4,5,6,7,8,9,10}; for (int i=0; i<10; i++) x.put(a[i]); // lista x sadrzi elemente niza a ListIterator i1(x), i2(x), i3(x); int p=i1(); // p postaje 1 a i1 se pomera na 2 int q=i2(3); // q postaje 1 a i2 se pomera na 4 p=i1(); // p postaje 2 a i1 se pomera na 3 i1()=0; // a[2] postaje 0 a i1 se pomera na 4 i3(-1); // i3 ostaje u mestu

52 Неки посебни оператори
Претходни пример претпоставља да ће итератори бити креиране за непразне листе али кодом није спречено другачије!

53 Неки посебни оператори
Нека је потребно креирати објекте класе XCaller која позива функције чланице неког објекта класе X. И овде ће бити згодно да се преклопи оператор () за класу XCaller.

54 Неки посебни оператори
typedef int T; // neki tip T class X; typedef T X::MF(T,T,T); // MF je tip funkcije: T X::(T,T,T) class X { // klasa X treba da ima funkciju clanicu tipa MF // … public: T f(T,T,T); // funkcija clanica f tipa MF T g(T,T,T); // funkcija clanica g tipa MF };

55 Неки посебни оператори
class XCaller { X &object; MF *pfunction; // pokazivac na funkcije clanice klase X public: XCaller(X &x, MF *pf) : object(x), pfunction(pf) {} // konstruktor T operator() (T t1,T t2,T t3) // poziva funkciju objekta { return object.*pfunction(t1,t2,t3);} };

56 Неки посебни оператори
X x1, x2; XCaller xc1(x1, &X::f), xc2(x1, &X::g), xc3(x2, &X::f); T a, b, c; xc1(a, b, c); // poziv, ustvari x1.f(a,b,c) xc2(a, b, c); // poziv, ustvari x1.g(a,b,c) xc3(a, b, c); // poziv, ustvari x2.f(a,b,c)

57 Неки посебни оператори
Операција индексирања облика izraz1[izraz2] сматра се бинарном операцијом где је izraz1 први операнд а izraz2 други. Одговарајућа операторска функција је operator[] која мора да буде нестатичка функција чланица неке класе X.

58 Неки посебни оператори
Ако је x објекат неке класе X, израз облика x[izraz] тумачи се као позив операторске функције чланице x.operator[] (izraz). Овај оператор се користи најчешће за индексирање објеката класа које представљају неке колекције (динамички низови, низови знакова, асоцијативни низови,...).

59 Неки посебни оператори
Асоцијативни низ је колекција објеката којима се приступа према вредности елемента (кључу).

60 Неки посебни оператори
class String { // … public: String (const char*); // konstruktor String (const String&); // konstruktor kopije friend int operator== (const String&, const String&); };

61 Неки посебни оператори
class ASArr { // asocijativni niz int dim; // dimenzija niza String **array; // sadrzaj niza public: static String empty; // prazan niz ASArr (int dimension); // konstruktor ASArr (const ASArr&); // konstruktor kopije ~ASArr (); // destruktor // … String& operator[] (int index); String& operator[] (const String&); };

62 Неки посебни оператори
String ASArr::empty=“”; // inicijalizacija statickog clana ASArr::ASArr (int d) : dim(d), array(new String*[d]) { for (int i=0; i<d; i++) array[i]=0; } // konstruktor alocira dinamicki niz ASArr::~ASArr () { for (int i=0; i<d; i++) delete array[i]; delete [] array; } // destruktor ukida dinamicki niz

63 Неки посебни оператори
String& ASArr::operator[] (int i) { // indeksira element if (!array[i]) return *(array[i]=new String(empty)); else return *array[i]; }

64 Неки посебни оператори
String& ASArr::operator[] (const String &s) { // asocijativna for (int i=0; i<dim; i++) // pretraga niza if (array[i] && (*array[i]==s)) return *array[i]; // poziva se operator== (String&, String&) if (s != empty) { error(“String not found!”); // trazeni element ne postoji return empty; // nesto se ipak vraca } else { for (int i=0; i<dim; i++) if (!array[i]) return *(array[i]=new String(empty)); if (i==dim) { error (“Array is full!”); return empty; }

65 Неки посебни оператори
void f() { String s1=”A”, s2=“B”, s3=“C”; ASArr a(4); a[0] = s1; a[1] = s2; a[2] = s3; String s4=a[1]; s4=a[“C”]; // asocijativni pristup a[ASArr::empty]=s4; // asocijativni pristup }

66 Неки посебни оператори
Операторска функција operator-> мора да буде нестатичка функција чланица без аргумената. Операција приступа члану, облика izraz1->izraz2 сматра се унарном операцијом где је операнд izraz1.

67 Неки посебни оператори
Ако је x објекат класе X, израз x->c тумачи се као (x.operator-> ())->c. Операторска функција треба да врати или показивач на класу која поседује члан c, или објекaт или референцу на класу за коју је дефинисан оператор ->.

68 Неки посебни оператори
Овај оператор се може користити у спрези са осталим операторима (као што су оператор дереференцирања показивача * и оператор доделе =) код класа које реализују показиваче са додатним могућностима (провера исправности показивача, бројање коришћења динамичких објеката, ...).

69 Неки посебни оператори
Нека класа Xptr реализује „паметни показивач“ на класу X, тако што се броји сваки приступ објекту класе X и било ком његовом члану преко показивача. Да би то било могуће, треба преклопити операторе * и ->.

70 Неки посебни оператори
struct X { int m; }; class Xptr { X *p; int usage; public: Xptr (X *px) : p(px), usage(0) {} // konstruktor Xptr (Xptr&); // konstruktor kopije // … X& operator* () { usage++; return *p; } // unarni operator * X* operator-> () { usage++; return p; } };

71 Неки посебни оператори
void main () { X x; Xptr p=&x; // p ukazuje na x *p.m=1; // poziva se (p.operator* ()).m int i=p->m; // poziva se (p.operator-> ()).m p->m=3 // takodje i ovde // … };

72 Неки посебни оператори
Оператор доделе = се може преклопити дефинисањем операторске функције operator= за неку класу X. Ова функција мора да буде нестатичка функција чланица класе. Ако је x објекат класе X, израз облика x=izraz тумачи се као позив x.operator= (izraz).

73 Неки посебни оператори
Ова операторска функција је једина која се не наслеђује. Кад год подразумевани поступак додељивања за неку класу није примерен, треба дефинисати ову операторску функцију. Ако је потребан конструктор копије, обично је потребан и овај оператор.

74 Неки посебни оператори
class X { int *pi; // ukazuje na pridruzeni dinamicki objekat public: X(int i) : pi(new int(i)) {} // konstruktor X(const X&) : pi(new int(*x.pi)) {} // konstruktor kopije X& operator= (const X&); // operator dodele ~X() { delete pi; } // destruktor // … };

75 Неки посебни оператори
X& X::operator= (const X& x) { if (this!=&x) { // provera da nije dodela x=x delete pi; pi=new int(*x.pi); }; return *this; }

76 Неки посебни оператори
extern X f(X); // funkcija f sa argumentom i rezultatom tipa X void g() { X xa=3, xb=1; // objekti xa i xb tipa X X xc=xa; // poziva se konstruktor kopije // … xa=f(xb) // poziva se konstruktor kopije samo za // formalni argument x, a za xa se poziva // xa.operator= (f(xb)) xc=xa; // poziva se xc.operator=(xa) }

77 Неки посебни оператори
Треба разликовати иницијализацију од доделе. Иницијализација подразумева да објекат који се иницијализује још увек не постоји. Приликом иницијализације се позива конструктор (конструктор копије) док се додела врши операторском функцијом operator=.

78 Неки посебни оператори
Ако класа има конструктор копије, оператор доделе или деструктор, најчешће то значи да мора да има све три функције.

79 Конверзије типова Један начин да се изврши корисничка конверзија је дефинисањем конструктора класе X који се може позвати са једним аргументом Y при чему се врши конверзија Y у X. Други начин је да се декларише посебна операторска функција чланица која дефинише конверзију.

80 Конверзије типова Оваква операторска функција чланица класе X има облик operator tip при чему се конвертује тип X у тип tip.

81 Конверзије типова class complex { double real, imag; public: complex (double r=0, double i=0) :real(r), imag(i) {} operator double() { return real; } // konverzija iz complex u double // … };

82 Конверзије типова void f() { complex c(3.4,6); double d1=c,// implicitna konverzija iz complex u double d2=0; d2=5.0+double(c); // eksplicitna konverzija iz complex u // double d2= (double) c-3; // isto ali sada cast // … }

83 Основни стандардни УИ токови
Све УИ операције реализоване су као библиотечке функције. Могу се примењивати УИ функције из језика C, али је то превазиђено. Библиотека са декларацијама у <iostream.h> садржи класе istream и ostream које реализују улазне и излазне токове.

84 Основни стандардни УИ токови
Осим овога ту је и: cin, глобални статички објекат придружен стандарном улазном уређају; cout, глобални статички објекат придружен стандарном излазном уређају; operator>>, функција за улаз; operator<<, функција за излаз.

85 Основни стандардни УИ токови
#include <iostream.h> void main () { int i; cin>>i; // ucitava se i // pozivom cin.operator>>(int&) cout<<“i=“<<i<<‘\n’; // ispisuje se (npr.) i=5 i prelazi // u novi red }

86 Основни стандардни УИ токови
#include <iostream.h> class complex { double real, imag; friend ostream& operator<< (ostream&,complex); public: //… };

87 Основни стандардни УИ токови
ostream& operator<< (ostream &os ,complex c) { return os<<“(“<<c.real<<“,”<<c.imag<<“)”; } void main () { complex c(0.5,0.1); cout<<“c=“<<c<<‘\n’; // ispisuje se: c=(0.5,0.1)


Скинути ppt "Преклапање оператора Операторске функције Неки посебни оператори"

Сличне презентације


Реклама од Google