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

Slides:



Advertisements
Сличне презентације
Računarstvo i informatika
Advertisements

Програмски језик Parallaxis
Uvod u programiranje - matematika – XII predavanje Moduli. OOP
Показивачи у програмском језику C Дамјан Илић; Е32 Габриела Миленковић
Јазкот C++ Мандал Сениха.
Elektronički logički sklopovi i registri
Показивачи.
Programiranje - Nizovi -
Digitalna obrada signala u FPGA
Uvod u funkcije Kolegij: Programski jezik C++ Ak. god. 2018/19
Рад са графичким објектима
Tipovi, operatori i izrazi
3. 4. Дизајн статичких веб страна
Programiranje - Naredbe za kontrolu toka programa – 4. dio
Hierarchical Clustering
Nastavna jedinica: 1.5. Elektronički logički sklopovi i registri
UVOD, STRUKTURNA ANALIZA
Microsoft Access uvod u baze podataka.
OSNOVNI ELEMENTI PLC KONTROLERA
ЦЕЛОБРОЕН ТИП НА ПОДАТОЦИ
Uvod u programiranje - matematika – VI predavanje Petlje. FOR. WHILE
Konačni automati i regularni izrazi
Nastavna cjelina: 2. Microsoft Excel 2010
Parametarska sinteza regulatora (izbor parametara)
ПРОПОРЦИОНАЛНО-ИНТЕГРАЛНИ PI РЕГУЛАТОР
Nastavna jedinica: 1.5. Elektronički logički sklopovi i registry
Nastavna cjelina: 1. Osnove IKT-a
5 NAREDBE.
Dinamičke strukture podataka
Оператори и изрази Аритметички оператори Оператори на нивоу битова
VIŠEDIMENZIONI NIZOVI
OSNOVE PROGRAMIRANJA U VISUAL BASIC-U predavanje 6: kolekcija selektovanih objekata Blok, atributi, automatsko kreiranje linije i kružnice Replace this.
Увод у организацију и архитектуру рачунара 1
Funkcije.
Сабирање и одузимње преко 1000
Vježbe 1. dio - Razvojne okoline -
Naredba case Komanda "Select Case" se koristi kada u izrazu imamo više uslova. U sledećem primjeru prikazano je korištenje naredbe “If - else“ Izraz postaje.
Meni Home II dio.
Спецификатори Иницијализација
Uskladištene procedure
Uvod u programiranje - matematika – XII predavanje
Podaci.
Uvod u programiranje - matematika – V predavanje
Programiranje - Blokovi naredbi i logički tipovi –
BAZE PODATAKA.
JEZIK RAČUNALA: bit i bajt
Vježbenica 1c: Pravocrtna programska struktura
KREIRANJE GRAFIKONA U EXCEL-U
Projektovanje namenskih računarskih struktura u obradi signala
Strukture podataka i algoritmi 1
Napadi na web aplikacije
Programski jezik C++ - Vježbe - 3. dio
Vježbenica 3: struktura petlje – 1.dio
Osnovna Struktura programa
Tipkovnica engl. Keyboard.
Relacione baze –primer modelovanja baze
Структура програма у Паскалу
Logičko projektovanje računarskih sistema 2
Logičko projektovanje računarskih sistema 2
Algoritmi Vladimir Filipović
Процесорска поља Организација процесорских поља
Prof. dr Vlado Simeunović OSNOVE RAČUNARSKE TEHNIKE vlado
Funkcije u ekselu.
Kreiranje naloga Turnitin.com
МЕЂУНАРОДНИ ДАН ПИСМЕНОСТИ
Principi programiranja
Rešavanje problema pomoću računara
Vježbenica 3: struktura petlje – 2.dio
Синтакса програмских језика и опис синтаксе
Транскрипт презентације:

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

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

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

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

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

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

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

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

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

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

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

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

Операторске функције 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); }

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

Операторске функције 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); }

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

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

Операторске функције 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)); // …

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

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

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

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

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

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

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

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

Операторске функције 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); } //… };

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

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

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

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

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

Неки посебни оператори 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 }

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

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

Неки посебни оператори 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); }

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

Неки посебни оператори 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”

Неки посебни оператори 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 () //… };

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

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

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

Неки посебни оператори 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() };

Неки посебни оператори 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)

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

Неки посебни оператори 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 };

Неки посебни оператори 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 };

Неки посебни оператори 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);} };

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

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

Неки посебни оператори 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

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

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

Неки посебни оператори 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 };

Неки посебни оператори 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);} };

Неки посебни оператори 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)

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

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

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

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

Неки посебни оператори 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&); };

Неки посебни оператори 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

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

Неки посебни оператори 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; }

Неки посебни оператори 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 }

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

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

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

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

Неки посебни оператори 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; } };

Неки посебни оператори 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 // … };

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

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

Неки посебни оператори 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 // … };

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

Неки посебни оператори 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) }

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

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

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

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

Конверзије типова 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 // … };

Конверзије типова 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 // … }

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

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

Основни стандардни УИ токови #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 }

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

Основни стандардни УИ токови 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)