Title: Objektno orijentirano programiranje http://www.oss.unist.hr/~ncaklovi/oop
1Objektno orijentirano programiranje
http//www.oss.unist.hr/ncaklovi/oop
- Nenad Caklovic
- nenad.caklovic_at_oss.unist.hr
21. predavanje
- odlike objektnog programiranja
- uvod u programski jezik C
- razlike C i C
3Objektno programiranje
- problemi proceduralnog programiranja
- teško održavanje velikih projekata
- osjetljivost na promjene u implementaciji
- nemogucnost dodavanja novih tipova i redefinicije
operatora - odlike objektno orijentiranog programiranja
- apstrakcija podataka (data abstraction)
- enkapsulacija (encapsulation)
- skrivanje podataka (data hiding)
- polimorfizam (polymorphism)
- dinamicko povezivanje (dynamic binding)
- nasljedivanje (inheritance)
- pravila cistog objektnog programiranja
- sve je objekt
- program je hrpa objekata koji komuniciraju
porukama - svaki objekt ima svoje podatke sastavljene od
drugih objekata - svaki objekt ima tip
- svi objekti istog tipa mogu primati iste poruke
4Programski jezik C
- 1979. Bjarne Stroustrup u Bellu (sadašnji ATT) -
C s klasama - 1983. C, dodatna proširenja
- 1989. osnovan ANSI komitet za standardizaciju C
na osnovu ARM-a (Annotated C Reference Manual) - 1998. usvojen ISO standard
- još uvijek traje petogodišnji moratorij na
promjene standarda - literatura
- Bjarne Stroustrup The C Programming Language
- usenet
- comp.lang.c
- comp.std.c
- C se može koristiti i samo kao bolji C
5void
- ne mora se pisati void kao argument funkcije
- C
- int main(void)
- return 0
-
6komentari
- jednolinijski komentari, pocinju sa //
- C
- / returns square /
- int f(int n)
- / int i, s0
- for(i0 iltn i)
- s n
- return s
- /
- return nn / easier /
- C
- // returns square
- int f(int n)
- / int s0
- for(int i0 iltn i)
- s n
- return s
- /
- return nn // much easier
7deklaracija varijabli
- varijable se mogu deklarirati bilo gdje unutar
funkcije
- C
- int f(char s, int n)
- int i, c 0
- char p s
- if(!p)
- return 0
- for(i0 iltn i)
- if(pi 'a')
- c
- return c
- C
- int f(char s, int n)
- char p s
- if(!p)
- return 0
- int c 0
- for(int i0 iltn i)
- if(pi 'a')
- c
- return c
8bool
- novi tip, može imati vrijednosti true i false
- C
- int f(int n)
-
- if(n lt 0)
- return 1
- return 0
-
- int main(void)
-
- int x -3
- int b f(x)
- if(b)
- x abs(x)
- return 0
- C
- bool f(int n)
-
- if(n lt 0)
- return true
- return false
-
- int main()
-
- int x -3
- bool b f(x)
- if(b)
- x abs(x)
-
9operator
- omogucava pristup skrivenim globalnim varijablama
- C
- int n
- int main(void)
-
- int n
- for(n0 nlt10 n)
- n
- return 0
-
- C
- int n
- int main()
-
- for(int n0 nlt10 n)
- n
-
10pretpostavljene vrijednosti argumenata
- zadnji argumenti funkcije mogu imati
pretpostavljenu (default) vrijednost
- C
- int f(int n, int b)
-
- return n b 0
-
- int main(void)
-
- f(10, 5)
- f(9, 3)
- f(8, 2)
- return 0
-
- C
- bool f(int n, int b 2)
-
- return n b 0
-
- int main()
-
- f(10, 5)
- f(9, 3)
- f(8)
-
11overloading funkcija
- mogu postojati funkcije istog imena, razlicitih
tipova argumenata
- C
- include ltcstdiogt
- void print(int n)
-
- printf(d\n, n)
-
- void print(double n)
-
- printf(lf\n, n)
-
- int main()
-
- print(10)
- print(3.14)
- C
- include ltstdio.hgt
- void print_int(int n)
-
- printf(d\n, n)
-
- void print_double(double n)
-
- printf(lf\n, n)
-
- int main(void)
-
- print_int(10)
- print_double(3.14)
- return 0
12reference
- C
- void swap(int a, int b)
-
- int t
- if(!a !b)
- return
- t a
- a b
- b t
-
- int main(void)
-
- int x5, y7
- swap(x, y)
- return 0
- C
- void swap(int a, int b)
-
- int t a
- a b
- b t
-
- int main()
-
- int x5, y7
- swap(x, y)
-
13reference
- referenca mora biti inicijalizirana
- double d 1.25
- double r d
- referenca se ne može promijeniti, sve operacije
na referenci se odnose na varijablu na koju
referenca pokazuje - int n 1
- int r n
- r 3 // mijenja vrijednost varijable n
- preko konstantne reference ne može se mijenjati
ni varijabla na koju referenca pokazuje -
- int n 1
- const int r n
- r 3 // compile error
14Hello world!
- include ltiostreamgt
- int main()
-
- stdcout ltlt "Hello world!" ltlt stdendl
-
152. predavanje
16Objekti
podaci
operacije nad podacima
17objekt
- // date.h
- struct date
- int year
- int month
- int day
-
- void set_date(struct date, int y, int m, int d)
- void current_date(struct date)
- void print_date(const struct date)
- void next_date(struct date)
18C implementacija
- // date.c
- include ltstdio.hgt
- include "date.h"
- void set_date(struct date dt, int y, int m, int
d) - dt-gtyear y dt-gtmonth m dt-gtday d
-
- void current_date(struct date dt)
- dt-gtyear 2002 dt-gtmonth 4 dt-gtday 19
-
- void print_date(const struct date dt)
- printf("02d.02d.d.", dt-gtday, dt-gtmonth,
dt-gtyear) -
- void next_date(struct date dt) //
oversimplified - dt-gtday
- if(dt-gtday gt 30) dt-gtday - 30 dt-gtmonth
19funkcije clanovi
- // date.h revisioned
- struct date
- int year
- int month
- int day
- void set(int y, int m, int d)
- void get(int y, int m, int d) const
- void current()
- void print() const
- void next()
-
20C implementacija
- // date.cpp
- include ltiostreamgt
- include "date.h"
- void dateset(int y, int m, int d)
- year y month m day d
-
- void dateget(int py, int pm, int pd) const
- py year pm month pd day
-
- void dateprint() const
- stdcout ltlt day ltlt '.' ltlt month ltlt '.' ltlt year
ltlt '.' -
- void datenext() // oversimplified
- day
- if(day gt 30) day - 30 month
21upotreba objekata
- upotreba strukture iz C i C
- C
- int main(void)
-
- struct date d
- current_date(d)
- next_date(d)
- print_date(d)
- return 0
C int main() date d d.current() d.next()
d.print()
22class
- // date.h rerevisioned
- struct date
- private
- int year
- int month
- int day
- public
- void set(int y, int m,
- int d)
- void get(int y, int m,
- int d) const
- void current()
- void print() const
- void next()
-
- // date.h rerevisioned
- class date
- int year
- int month
- int day
- public
- void set(int y, int m,
- int d)
- void get(int y, int m,
- int d) const
- void current()
- void print() const
- void next()
-
23private, public
- samo objekt smije pristupati svojim privatnim
clanovima
- class X
- int n
- bool test()
- public
- void work(X other)
int main() X x1, x2 int n x1.n //
error if(x1.test()) // error return
1 x1.work(x2) // OK return 0
24private, public
- samo objekt i drugi objekti istog tipa smiju
pristupati privatnim clanovima objekta
- class X
- int n
- bool test()
- public
- void work(X other)
// all OK void Xwork(X other) if(!test())
return if(other.test()) n other.n
25const funkcije
- const funkcija clan ne može mijenjati objekt
- class integer
- int n
- public
- int read() const
- void write(int i)
// 1st version, all OK int integerread() const
return n void integerwrite(int i) n i
// 2nd version, illegal int integerread() const
if(n lt 0) n 0 // error! return n
26const funkcije
- na konstantnim referencama se mogu zvati samo
konstantne funkcije
- void f(integer x, const integer y)
-
- int a x.read() // OK
- x.write(5) // OK
- int b y.read() // OK
- y.write(8) // error!
-
27inline funkcije
- definicija funkcije clana se može pisati u
tijelu klase
- class integer
- int n
- public
- int read() const return n
- void write(int i) n i
class integer int n public int read()
const void write(int i) inline int
integerread() const return n inline void
integerwrite(int i) n i
28this
- za svaku klasu T postoji skriveni const pointer
T const this
- class integer
- int n
- public
- int read() const return n
- void write(int i) n i
class integer int n public int read() const
return this-gtn void write(int i) this-gtn
i
29this
- koristi se i kada iz funkcije clana treba
poslati pointer ili referencu na objekt
- void print1(date dt)
- int d, m, y dt-gtget(d, m, y)
- stdcout ltlt d ltlt '.' ltlt m ltlt '.' ltlt y ltlt '.'
-
void print2(const date dt) int d, m, y
dt.get(d, m, y) stdcout ltlt d ltlt '.' ltlt m
ltlt '.' ltlt y ltlt '.'
void dateprint() const print1(this) pri
nt2(this)
303. predavanje
- stvaranje objekata
- inicijalizacija objekata
31dinamicka alokacija u C
- operatori new, delete i delete
int pn new int15 date pd new date3
- int pn new int
- float pf new float
- date pd new date
delete pn pn 0 delete pd pd 0
delete pn delete pf delete pd
pn 0 pf 0 pd 0
32konstruktor, destruktor
- posebne funkcije clanovi, nemaju tip povratne
vrijednosti - konstruktor
- za klasu T naziv funkcije je T()
- poziva se pri stvaranju objekta
- destruktor
- za klasu T naziv funkcije je T()
- poziva se pri uništenju objekta
33konstruktor, destruktor
int main() screen s s.draw("Hello!")
- class screen
- int width, height
- public
- screen()
- screen()
- bool draw(const char txt)
int main() screen ps new screen ps-gtdraw("H
ello!") delete ps
screenscreen() width 1024 height
768 fill_screen(1)
screenscreen() fill_screen(0)
34konstruktor sa argumentima
- class screen
- int width, height
- public
- screen(int width, int height)
- screen()
- bool draw(const char txt)
screenscreen(int w, int h) width w height
h
screenscreen(int width, int height)
this-gtwidth width this-gtheight height
screenscreen(int w, int h) width(w),
height(h)
screenscreen(int width, int height)
width(width), height(height)
35konstruktor sa argumentima
- int main()
- screen s(1024, 768)
- s.draw("Hello again!")
- i built-in tipovi imaju konstruktor
int width(1024), height(768) double
r(7.24) bool f(false)
int pn new int(42) unsigned long pl new
unsigned long(666)
36primjer citanje iz datoteke (C)
- int main(void)
- char head40, data256
- FILE fp fopen("a.bmp", "r")
- if(!fp)
- return 1
- if(!fread(head, 40, fp))
- fclose(fp)
- return 2
-
- if(!fread(data, 256, fp))
- fclose(fp)
- return 3
-
- show_picture(data)
- fclose(fp)
- return 0
37primjer citanje iz datoteke (C)
- class file
- FILE fp
- public
- file(const char)
- file()
- bool open()
- int read(void, int)
-
- filefile(const char name)
- fp fopen(name, "r")
-
- filefile()
- if(fp) fclose(fp)
-
- ...
int main() char head40, data256 file
f("a.bmp") if(!f.open()) return
1 if(!f.read(head, 40)) return
2 if(!f.read(data, 256)) return
3 show_picture(data) return 0
38default konstruktor
- konstruktor koji se može pozvati bez argumenata
- kada klasa nema konstruktora, generira se
default konstruktor
- kada pravimo polja objekata, objekt mora imati
default konstruktor
int main() point pts8 return 0
- class point
- int x, y
- public
- point() x(0), y(0)
int main() point p new point8 delete
p
class point int x, y public point(int x0,
int y0) x(x), y(y)
39copy konstruktor
- konstruktor koji kao prvi argument prima
referencu na drugi objekt istog tipa
- class point
- int x, y
- public
- point(int x, int y)
- point(const point other)
-
- pointpoint(int ix, int iy) x(ix), y(iy)
- pointpoint(const point other) x(other.x),
y(other.y) - int main()
- point p1(1, 0)
- point p2(p1)
-
40inicijalizacija
- clanovi se inicijaliziraju redoslijedom kojim su
navedeni u tijelu klase
- class point
- int x, y
- public
- point(int x, int y)
-
- pointpoint(int ix, int iy) y(iy), x(ix)
41class objekti kao clanovi
- prvo se pozivaju konstruktori clanova, a zatim
konstruktor objekta
- class interval
- point start
- point end
- public
- interval(int x1, int y1, int x2, int y2)
- interval(const point p1, const point p2)
-
- intervalinterval(int x1, int y1, int x2, int
y2) - start(x1, y1), end(x2, y2)
- intervalinterval (const point p1, const point
p2) - start(p1), end(p2)
424. predavanje
43staticki clanovi (static members)
- dijele ih svi objekti istog tipa
- ekvivalent globalnih varijabli/funkcija u C-u
- // track.h
- class track
- static int numobj // static member
- public
- track()
- track()
- static void print_name() // static member
function
// track.cpp int tracknumobj 0
tracktrack() numobj tracktrack()
--numobj void trackprint_name() stdcout
ltlt "track"
44operator
- može se pisati pri pristupu clanovima objekta
- obavezan pri pristupu statickim clanovima
- class point
- int x, y
- public
- double length()
-
- double pointlength() return sqrt(xx yy)
- int main()
- point p
- double n1 p.pointlength() // isto kao
p.length() - point pp p
- double n2 pp-gtpointlength() // isto kao
pp-gtlength()
45namespace
- grupiranje globalnih simbola (funkcija, tipova i
varijabli)
- // oop.h
- namespace oop
-
- class point public int x, y
- double distance(const point p1, const point
p2) -
- // oop.cpp
- double oopdistance(const point p1, const
point p2) - int a(p1.x-p2.x), b(p1.y-p2.y)
- return sqrt(aa bb)
-
46namespace
- korištenje simbola - operator ili 'using
namespace'
- int main()
- ooppoint p1, p2
- double len oopdistance(p1, p2)
int main() using namespace oop point p1,
p2 double len distance(p1, p2)
47std namespace
- stdcin, stdcout, stdstring
- include ltiostreamgt
- include ltstringgt
- int main()
- using namespace std
- string s cin gtgt s
- cout ltlt s ltlt " ima " ltlt s.length() ltlt "
znakova." ltlt endl - char c cin gtgt c
- int pos s.find(c)
- if(pos gt 0)
- cout ltlt "slovo " ltlt c ltlt " se prvi puta
pojavljuje na " ltlt pos ltlt ". mjestu" ltlt endl
48nasljedivanje
- class person
- string name
- date birth
- string address
- ...
class student person p short
schoolYear float averageMark ...
class student string name date
birth string address short schoolYear float
averageMark ...
class student person short
schoolYear float averageMark ...
49bazna klasa, izvedena klasa
- izvodenje ili nasljedivanje
- bazna klasa (base class, superclass)
- izvedena klasa (derived class, subclass)
- built-in tip ne može biti bazna klasa
50poziv funkcija bazne klase
- funkcije clanovi bazne klase se pozivaju preko
operatora
- void personprint()
- stdcout ltlt name ltlt birth ltlt address
void studentreport() personprint() stdco
ut ltlt schoolYear ltlt averageMark
51protected
- objekti izvedenih klasa smiju pristupati
protected clanovima
- class person
- protected
- string name
- date birth
- string address
class student public person short
schoolYear float averageMark public bool
check_status() return schoolYear lt 2
birth.year lt 1980
52upcasting
- objekt izvedene klase se može tretirati kao
objekt bazne klase preko reference ili pointera
- int main()
- person p
- student s
- person p1 p // ili person p1 p
- student s1 s // ili student s1 s
- person p2 s // OK, svaki 'student' je
'person' - person p3 s // OK
- student s2 p // error! -gt p nije student
- student s3 p // error!
- student s4 p2 // error! (iako p2 pokazuje na
studenta)
53private, protected izvodenje
- privatno izvodenje skriva clanove bazne klase
- protected izvodenje skriva clanove bazne klase,
ali ne od izvedenih klasa
- class A
- public
- int i
-
- class B private A
- int main()
- B b
- b.i 1 // error!
class B protected A class C public B
public void f() i 0 int
main() C c c.i 1 // error!
54inicijalizacija
1. konstruktor bazne klase2. konstruktori
clanova3. konstruktor objekta
- personperson(const string n, int y, int m, int
d, const string a) name(n), date(y, m, d),
address(a) - studentstudent(const string n, int y, int m,
int d, const string a, short sy) person(n, y,
m, d, a), schoolYear(sy)
- destruktori se pozivaju obrnutim redom
55skrivanje funkcija
- istoimena funkcija u izvedenoj klasi skriva
funkciju u baznoj klasi
- class person
- public
- void print()
-
- class student public person
- public
- void print()
-
- int main()
- student s
- s.print()
- s.personprint()
-
56virtualne funkcije
- virtualna funkcija se može pregaziti (override)
u izvedenoj klasi
- poziv funkcije je poziv u zadnjoj izvedenoj
klasi koja je pregazila funkciju (osim u
konstruktoru i destruktoru)
- class instrument
- public
- virtual void play()
-
- class drum public instrument
- public
- void play()
- cout ltlt "dum, dum"
-
-
- class piano public instrument
- public
- void play()
- cout ltlt "pling"
-
int main () instrument i piano p drum
d instrument pi i pi-gtplay() // - pi
p pi-gtplay() // pling pi
d pi-gtplay() // dum, dum
575. predavanje
- virtualne funkcije
- višestruko nasljedivanje
58mehanizam virtualnih funkcija
- velicina objekta naraste za 4 byte-a cim ima
barem jednu virtualnu funkciju
- pointer (vptr) na tablicu virtualnih funkcija
(vtable)
- class virt0
- int n
- public
- void f()
-
- class virt1
- int n
- public
- virtual void f()
-
- class virt2
- int n
- public
- virtual void f()
- virtual void g()
int main () using namespace std virt0
v0 cout ltlt sizeof(v0) // 4 virt1 v1 cout
ltlt sizeof(v1) // 8 virt2 v2 cout ltlt
sizeof(v2) // 8
59mehanizam virtualnih funkcija
- class virt2
- int n
- public
- virtual void f()
- virtual void g()
-
- int main()
- virt2 a, b
- tablica virtualnih funkcija vrijedi za sve
objekte klase
- tablica virtualnih funkcija se inicijalizira u
konstruktoru
- sve funkcije osim konstruktora mogu biti
virtualne
60virtualni destruktor
- obavezan ako ce se uništavanje objekata vršiti
preko pointera na baznu klasu
- class instrument
- public
- virtual void play()
- virtual instrument()
int main () instrument pins new
instrument, new piano, new drum, for(int
i0 ilt3 i) pinsi-gtplay() for(int j0
jlt3 j) delete pinsj
61cisto virtualne funkcije (pure virtual functions)
- cisto virtualne funkcije se oznacavaju sa 0 u
deklaraciji
- class instrument
- public
- virtual void play() 0
- cisto virtualne funkcije mogu imati definiciju
class instrument public virtual void play()
0 void instrumentplay() cout ltlt "moj
zvuk "
class piano public instrument
public virtual void play() void
pianoplay() instrumentplay() cout ltlt
"pling" ltlt endl
62apstraktna klasa (abstract class)
- klasa sa bar jednom cisto virtualnom funkcijom
- nije moguce napraviti objekt apstraktne klase,
koriste se pointeri i reference na njih
- cisto virtualni destruktor mora imati definiciju
- class instrument
- public
- virtual void play() 0
- virtual void tune() 0
- virtual instrument() 0
-
- instrumentinstrument()
apstraktna klasa samo sa cisto virtualnim
funkcijama cisto apstraktna (pure abstract)
klasa interface
63višestruko nasljedivanje (multiple inheritance)
- izvedena klasa ima više baznih klasa
- class phone
- public
- virtual void call(int)
- virtual void hangup()
- virtual void redial()
-
- class device
- public
- virtual void on()
- virtual void off()
-
- class moveable
- protected
- point GPScoord
- public
- virtual point coords()
class mobile_phone public phone, public
device, public moveable
int main() mobile_phone mp mp.on() mp.call(2
38729) point p mp.coords()
64inicijalizacija
1. konstruktori baznih klasa, redom kojim su
bazne klase navedene2. konstruktori clanova3.
konstruktor objekta
- class A
- public
- A() cout ltlt "A"
- A() cout ltlt "A"
-
- class B
- public
- B() cout ltlt "B"
- B() cout ltlt "B"
-
- class M
- public
- M() cout ltlt "M"
- M() cout ltlt "M"
class C public A, public B M
m public C() cout ltlt "C" C() cout ltlt
"C" int main() C c cout ltlt endl
ABMC CMBA
65višestruko pojavljivanje baze
- ista bazna klasa se pojavljuje više puta u
hijerarhiji
- više instanci bazne klase je sadržano u instanci
izvedene klase
- class auto
- protected
- engine e
-
- class auto1 public auto ... // ima servo
- class auto2 public auto ... // ima klimu
- class auto3 public auto ... // ima ABS
- class auto4 public auto ... // ima zr.
jastuke - class perfect_auto
- public auto1,
- public auto2,
- public auto4
-
-
- / has 3 engines ! /
66virtualno izvodenje (virtual inheritance)
- omogucava da se ista bazna klasa pojavi više
puta u hijerarhiji, a da je u izvedenoj klasi
sadržana samo jednom
- konstruktor virtualne baze se mora pozvati u
najizvedenijoj klasi
- class person
- protected
- string name
- public
- person(const string name) name(name)
-
- class student virtual public person ...
- class employee virtual public person ...
- class emp_student public student, public
employee - public
- emp_student(const string name) person(name)
-
676. predavanje
68friend
- klasa može omoguciti nekoj funkciji pristup
njenim private clanovima
- friend se može napisati bilo gdje u tijelu klase
- class Number
- int n
- public
- Number(int n) n(n)
- friend Number sum(const Number a, const Number
b) -
- Number sum(const Number a, const Number b)
- return Number(a.n b.n)
-
- int main()
- Number n1(3), n2(4)
- Number n3 sum(n1, n2)
-
69friend
- friend se može pisati i za funkcije clanove
- class A
- int n
- friend void Bf(A)
class B void f(A a) a.n
- pokrata za sve funkcije clanove neke klase
friend class
class A int n friend class B
class B void f(A a) a.n void g(A a)
--a.n
- friend nije tranzitivan i ne nasljeduje se
izvodenjem
class A friend class B class B friend
class C class C // C nije friend od
A class D public B // D nije friend od A
70operatori
- funkcija cije je ime "operator_at_"
- class Number
- int n
- public
- Number(int n) n(n)
- friend Number operator(const Number a, const
Number b) -
- Number operator(const Number a, const Number
b) - return Number(a.n b.n)
-
- int main()
- Number n1(3), n2(4)
- Number n3 n1 n2
-
71operatori
- može se pisati i kao funkcija clan
- class Number
- int n
- public
- Number(int n) n(n)
- Number operator(const Number b)
-
- Number Numberoperator(const Number other)
- return Number(n other.n)
-
- int main()
- Number n1(3), n2(4)
- Number n3 n1 n2
-
72preopterecenje operatora (operator overloading)
- operatori koji se mogu preopteretiti
- - / !
- lt gt - /
- ltlt gtgt gtgt ltlt ! lt gt
- -- -gt , -gt () new delete
- važna pravila1. ne mogu se definirati novi
operatori2. ne može se mijenjati prioritet
operatora3. ne mogu se mijenjati sintaksna
pravila
- binarni operatori1. globalna funkcija sa 2
argumenta (barem jedan od argumenata mora biti
user-defined tip!) ili2. funkcija clan sa jednim
argumentom
- unarni operatori1. globalna funkcija sa 1
argumentom ili2. funkcija clan bez argumenata
- operatori koji se moraju pisati kao clanovi
() -gt
73primjeri preopterecenja operatora
- class Byte
- char n
- public
- Byte(unsigned char n0) n(n)
- Byte operator() const return Byte(n)
- Byte operator-() const return Byte(-n)
- Byte operator(const Byte other) n
other.n return this - friend Byte operator(const Byte b1, const
Byte b2) - friend Byte operator-(const Byte b1, const
Byte b2) -
- Byte operator(const Byte b1, const Byte b2)
- return Byte(b1.n b2.n)
-
- Byte operator-(const Byte b1, const Byte b2)
- return Byte(b1.n - b2.n)
74inkrement i dekrement
- da bi se razlikovali prefiksna i postfiksna
verzija uvodi se dodatni argument
- class Number
- int n
- public
- Number(int n) n(n)
- Number operator() return Number(n)
- Number operator(int) return Number(n)
- friend Number operator--(Number)
- friend Number operator--(Number, int)
-
- Number operator--(Number a) return --a.n
- Number operator--(Number a, int) return a.n--
75operatori ltlt, gtgt
- za unos i ispis objekata klase
- class point
- int x, y
- friend istream operatorgtgt(istream, point)
- friend ostream operatorltlt (ostream os, const
point a) -
- istream operatorgtgt(istream is, point p)
- is gtgt p.x gtgt p.y
- return is
-
- ostream operatorltlt (ostream os, const point
p) - os ltlt '(' ltlt p.x ltlt ',' ltlt p.y ltlt ')'
- return os
-
- int main()
- point p
- cin gtgt p
- cout ltlt p
76operatori implicitne pretvorbe (conversion
operators)
- funkcija cije je ime "operator tip", nema tip
povratne vrijednosti
- class Number
- int n
- public
- Number(int n0) n(n)
- operator int() return n
-
- int main()
- Number a
- int b 2 a // 2 a.operator int()
77operator
- ako nije napisan, generira ga compiler (slicno
ako copy konstruktor)
- class Number
- int n
- public
- Number(int n0) n(n)
- Number(const Number other)
- Number operator(const Number other)
-
- int main()
- Number a, b
- Number c a // poziva copy konstruktor!
- b a // poziva operator
Number Numberoperator(const Number other)
n other.n return this
NumberNumber(const Number other) this
other // koristi op
78privremeni objekti (temporary objects)
- nastaju prvi svakom slanju objekata u funkciju i
vracanju objekata iz funkcije
- class A
- int n
- public
- A(int n) n(n) cout ltlt "A"
- A(const A other) n other.n cout ltlt "A"
- A() cout ltlt "A"
-
- A f(A a)
- return a // poziva copy konstruktor! (return
type objekt) -
- int main()
- A a(3)
- f(a) // poziva copy konstruktor! (argument
funkcije objekt)
79operator
- kao indeks (argument) može primiti bilo koji tip
- može služiti za stvaranje asocijativnih polja
- int main()
- assoc a
- string s
- while(true)
- cin gtgt s
- if(s.length()lt1)
- break
- as
-
- cout ltlt a
struct snpair string s int count snpair()
count(0)
80operator
- class assoc
- snpair arr256
- int last
- public
- assoc() last(0)
- int operator(const string s)
- friend ostream operatorltlt(ostream os, const
assoc)
int assocoperator(const string s)
for(int i0 iltlast i) if(arri.s
s) return arri.count arrlast.s
s return arrlast.count ostream
operatorltlt (ostream os, const assoc
a) for(int i0 ilt256 i) if(a.arri.count)
os ltlt a.arri.s ltlt " " ltlt a.arri.count
ltlt endl return os
81operator()
- ako funkcija ima staticke parametre, može se
napisati kao klasa (functional object)
- class translate
- int cx, cy
- public
- translate(int cx, int cy) cx(cx), cy(cy)
- point operator()(point p) p.x cx p.y
cy return p -
- // translate all points for vector (3,4)
- int main()
- translate t(3, 4)
- point p
- while(1)
- cin gtgt p
- t(p)
- cout ltlt p
-
827. predavanje
83template klase
- class IntArray
- int p
- public
- IntArray(int size) p(new intsize)
- IntArray() delete p
- int operator(int i) return pi
class DoubleArray double p public DoubleArr
ay(int size) p(new doublesize)
DoubleArray() delete p double
operator(int i) return pi
int main() IntArray ar1(10) DoubleArray
ar2(20)
84template klase
- klasa parametrizirana tipom (ili tipovima)
- templatelttypename Tgt
- class Array
- T p
- public
- Array(int size) p(new Tsize)
- Array() delete p
- T operator(int i) return pi
int main() Arrayltdoublegt ar1(10) Arrayltintgt
ar2(10)
85template klase - definicija clanova
- non-inline definiciju funkcija clanova prethodi
templatelttypename Tgt
- templatelttypename Tgt
- class Array
- T p
- public
- Array(int size)
- Array()
- T operator(int i)
templatelttypename Tgt ArrayltTgtArray(int size)
p(new Tsize) //templatelttypename Tgt
ArrayltTgtArrayltTgt(int size) p(new Tsize)
templatelttypename Tgt ArrayltTgtArray()
delete p templatelttypename Tgt T
ArrayltTgtoperator(int i) return pi
86template funkcije
- funkcija parametrizirana tipom (ili tipovima)
- void swap(int a, int b)
- int t a
- a b
- b t
templatelttypename Tgt void swap(T a, T b) T t
a a b b t
void swap(double a, double b) double t
a a b b t
int main() int n1, n2 swap(n1,
n2) swapltintgt(n1,n2)
void swap(Number a, Number b) Number t
a a b b t
87template funkcije clanovi (template member
functions)
- funkcija clan može biti template u template
klasi ili obicnoj klasi
- class A
- public
- templatelttypename Tgt
- T fun(T a) return aa
-
- int main()
- A a
- int n a.fun(5)
templatelttypename Tgt class A T m public A(T
t) m(t) templatelttypename ARGgt void
f(ARG a) cout ltlt ma int
main() Altunsigned chargt a(2) a.f(5)
88genericko programiranje
- moguci parametri template-a1. konstantni
izraz2. objekt ili funkcija3. pointer na clana
- templatelttypename Tgt vrijedi do kraja
klase/funkcije
- template može imati više parametara, zadnji mogu
imati default vrijednosti i ne moraju se navesti
(kao kod default vrijednosti argumenata funkcija)
templatelttypename T, int SIZE64gt class array
... int main() arrayltintgt
ar1 arrayltunsigned long, 32gt ar2
- template parametri funkcija se ne moraju
navesti, osim za return type
- templatelttypename Tgt T fun(int a) return aa
- int main() funltdoublegt(3)
89instanciranje (template instantiation)
- compiler obavlja male sintaksne provjere odmah,
kod za template klasu/funkciju nastaje tek pri
prvom spominjaju - instanciranje
- template lttypename Tgt
- class Array
- T p
- public
- Array(int size)
- Array()
- T operator(int i)
-
- template class Arrayltboolgt // eksplicitno!
- typedef Arrayltintgt IntArray
- int main()
- Arrayltfloatgt ar1(24) // implicitno
- IntArray ar2(32) // implicitno
90primjer
- templatelttypename Tgt void sort(vectorltTgt v)
- const size_t n v.size()
- for(int gapn/2 0ltgap gap/2)
- for(int igap iltn i)
- for(int ji-gap 0ltj j-gap)
- if(vjgap lt vj)
- swap(vj, vjgap)
- zahtjeva operatorlt na tipu T
91primjer
- templatelttypename Tgt bool less(T a, T b)
- return a lt b
-
- templatelttypename Tgt void sort(vectorltTgt v)
- const size_t n v.size()
- for(int gapn/2 0ltgap gap/2)
- for(int igap iltn i)
- for(int ji-gap 0ltj j-gap)
- if(less(vjgap, vj))
- swap(vj, vjgap)
// da bi sort stringova radio pravilno templateltgt
bool less(const char a, const char b)
return strcmp(a, b) lt 0
92specijalizacija (specialization)
- alternativna implementacija za pojedini tip
- templateltgt
- class Arrayltboolgt
- char p
- public
- Array(int size) p(new char(size-1)/81)
- Array() delete p
- bool operator(int i) return pi/8
(1ltlt(i8))
int main() Arrayltintgt ar1(30) // koristi
originalni template Arrayltboolgt ar2(64) //
koristi specijalizirani template
93parcijalna specijalizacija (partial
specialization)
- specijalizacija, ali ne po svim parametrima
- template lttypename T, typename U, typename Vgt
class A
template lttypename T, typename Vgt class AltT, int,
Vgt template lttypename Vgt class Altdouble,
long, Vgt template lttypename Ugt class Altint,
U, intgt
94eksplicitna konverzija (cast) u C
- static_cast - za uobicajene (C-ovske) pretvorbe
i upcasting
- int n5 double d static_castltdoublegt(n)
- Derived pd Base pb static_castltBasegt(pd)
- dynamic_cast - za downcast, vraca NULL ako ne
uspije
- klasa mora imati virtualne funkcije, potreban
RTTI (run-time type information)
Base b Derived d Base pb static_castltBasegt(
d) Derived pd dynamic_castltDerivedgt(pb)
Derived pd2 dynamic_castltDerivedgt(b) //
pd2 je NULL!
95eksplicitna konverzija (cast) u C
- const_cast - za skidanje i stavljanje
konstantnosti
void f(const A a) A ra const_castltAgt(a)
ra.change() A pa const_castltAgt(a)
pa-gtchange()
- reinterpret_cast - za kompletnu promjenu tipa,
opasno
void f(long lp) A pa reinterpret_castltAgt(lp
) int main() A a long xxx
reinterpret_castltlonggt(a) f(xxx) f(1) //
argh!!
968. predavanje
97iznimka (exception)
- kako signalizirati pogrešku iz operatora ili
konstruktora?
- funkcija baca (throw) iznimku
- funkcija pozivatelj hvata (catch) iznimku
- class X
- double square(double v)
- if(v lt 0) throw X()
- ...
- return s
int main() double d cin gtgt d try double
sq square(d) cout ltlt "square(" ltlt d ltlt ")
" ltlt sq ltlt endl catch(X) cout ltlt "invalid
input" ltlt endl
98iznimka je objekt
- objekt koji se baca može nositi poruku o greški
- class X
- public
- string err
- X(const char s) err(s)
-
- double square(double v)
- if(v lt 0) throw X("argument manji od nule")
- ...
-
- int main()
- double d cin gtgt d
- try
- double sq square(d)
- cout ltlt "square(" ltlt d ltlt ") " ltlt sq ltlt endl
- catch(X x)
- cout ltlt "error " ltlt x.err ltlt endl
-
99višestruki catch blokovi
- catch blokovi se provjeravaju redom koji su
napisani
- class XNeg
- class XSmall
- double square(double v)
- if(v lt 0) throw XNeg()
- if(v lt 0.01) throw XSmall()
- ...
-
- int main()
- double d cin gtgt d
- try
- double sq square(d)
- cout ltlt "square(" ltlt d ltlt ") " ltlt sq ltlt endl
- catch(XNeg x)
- cout ltlt "negativan broj" ltlt endl
- catch(XSmall x)
- cout ltlt "premali broj" ltlt endl
-
100hijerarhija iznimki
- obicno se koristi hijerarhija klasa iznimki
- class MathErr
- public
- virtual void ShowError() 0
-
- class ZeroDivide public MathErr
- public
- void ShowError() cout ltlt "dijeljenje s
nulom" -
- class Overflow public MathErr
- public
- void ShowError() cout ltlt "overflow"
-
- class Underflow public MathErr
- public
- void ShowError() cout ltlt "underflow"
-
101catch by reference
- catch bazne klase, obavezno reference da bi
radile virtualne funkcije
- int main()
- double d cin gtgt d
- try
- double sq square(d)
- cout ltlt "square(" ltlt d ltlt ") " ltlt sq ltlt endl
- catch(MathErr x)
- x.ShowError()
- catch(...)
- cout ltlt "nepoznata iznimka" ltlt endl
-
- catch(...) hvata sve ostale iznimke
- u slucaju da nitko ne uhvati iznimku zove se
stduncaught_exception()
- pri bacanju iznimke zovu se destruktori svih
objekata cija je inicijalizacija završena
- ne smije se throw-ati iz destruktora
102deklaracija funkcija
- za svaku funkciju može se specificirati koje
iznimke baca
- double f(double v) throw (X1, X2) // baca samo
X1, X2 i izvedene
void f(int n) throw() // ne baca
nista!
int g() // moze
baciti bilo sto!
class IntArray public ... int
operator(int index) throw (RangeError)
- ako funkcija baci neku drugu iznimku, zove se
stdunexpected()
- ako virtualna funkcija specificira set iznimki,
može se pregaziti sa funkcijom koja baca isti set
ili podskup
1039. predavanje
104standardna biblioteka (standard library)
- sve je unutar std namespace-a, u setu header-a
- include ltheadergt je obavezno zbog mogucih
optimizacija compilera
- uglavnom template-i, dozvoljeno je izvodenje i
specijalizacija
- podjela prema tipu (u zagradi su headeri)
- containeri (vector, list, deque, queue, stack,
map, set, bitset) - opci servisi (utility, functional, memory, ctime)
- iteratori (iterator)
- algoritmi (algorithm, ...)
- dijagnostika (exception, stdexcept, cassert, ...)
- stringovi (string, cctype, cwtpe, ...)
- ulaz/izlaz (iosfwd, iostream, ios, streambuf,
istream, ostream, iomanip, fstream, ...) - lokalizacija (locale, ...)
- podrška jeziku (limits, new, typeinfo,...)
- numerika (complex, valarray, numeric, ...)
- Standard Template Library (STL) - containeri,
algoritmi
105standardni containeri
- osobine
- type safe
- homogeni (svi elementi istog tipa)
- neintruzivni (elementi ne moraju biti izvedeni iz
bazne klase) - alokator kao dodatni template argument (za rad s
memorijom) - imaju "jednak" interface (standardni nazivi i
semantika)
- vrste
- sekvencijalni - vector, deque, list
- asocijativni (pristup po kljucu) - map, set,
multimap, multiset - posebni
- adapteri (sequence adapters) - stack, queue,
priority_queue - nepravi containeri - bitset, valarray, string
- sadržavaju (preko typedef-a)
- value_type, allocator_type, size_type,
difference_type - iterator, const_iterator, reverse_iterator,
const_reverse_iterator - pointer, const_pointer, reference, const_reference
- osnovne funkcije za pocetak i kraj sekvence
- begin(), end(), rbegin(), rend() - vracaju
iteratore
106iterator
- za pristup standardnim containerima koriste se
iteratori
- omogucavaju pristup razlicitim containerima na
isti nacin
- template lttypename Cgt
- Cvalue_type sum(const C c)
- Cvalue_type s 0
- for(Cconst_iterator it c.begin() it !
c.end() it) - s it
- return s
107vector
- funkcije za pristup elementima (vracaju
referencu) - operator(size_type index), at(size_type index)
- front(), back()
- at() provjerava indeks i baca out_of_range iznimku
- podržava funkcionalnost stack-a
- push_back(const value_type elem), pop_back()
- int main()
- vectorltintgt v
- v.push_back(2)
- v.push_back(7)
- typedef vectorltintgtconst_iterator Iter
- for(Iter it v.begin() it ! v.end() it)
- cout ltlt it ltlt endl
- // isto kao
- for(int i0 iltv.size() i)
- cout ltlt vi ltlt endl
108vector
- za dodavanje u sredinu (vraca iterator)
- insert(iterator pos, const value_type elem)
- za brisanje iz sredine (vraca iterator)
- erase(iterator pos)
- skupe operacije (zahtjevaju kopiranje preostalih
elemenata)
- za brisanje svih elemenata
- clear()
- funkcije vezane za velicinu
- size_type size() - broj elemenata u vectoru
- bool empty()
- void resize(size_type n, value_type val
value_type()) - dodane elemente inicijalizira sa
val - void reserve(size_type n) - alocira memoriju za n
elemenata - size_type capacity() - za koliko elemenata je
alocirana memorija
109ostali sekvencijalni containeri
- deque (double-ended queue)
- kao vector, dodatno podržava
- push_front(const value_type elem), pop_front()
- ima front operacije, nema direktnog pristupa
elementu (operator )
- koristi dvosmjerne iteratore pa je obicno
dvostruko povezana lista
- dodatna funkcionalnost
- splice(iterator pos, list x) - prebaci sve
element iz x ispred pos - sort() - sortiraj listu (koristi operatorlt)
- merge(list x) - spoji listu x (x ostaje prazan)
110adapteri
- koriste sekvencijalne containere, ali imaju svoj
interface
- po defaultu koristi deque (kao protected member),
ali ima svoje funkcije - push(), pop(), top()
- po defaultu koristi deque (kao protected member),
ali ima svoje funkcije - push(), pop(), front(), back()
- slicno kao queue (po defaultu koristi vector),
ali elementi imaju prioritet kojim dolaze na
top() - po defaultu operatorlt
111map
- drži parove kljuc-vrijednost (value_type je
stdpairltgt), kljuc mora biti jedinstven
- operator(const key_type key) - dodaje novi
element ako ne nade postojeci
- sortira elemente (po defaultu operatorlt) da bi
iteriranje išlo redom
- int main()
- mapltstring, intgt m
- while(true)
- string s cin gtgt s
- if(s.length()lt1) break
- ms
-
- typedef mapltstring, intgtconst_iterator Iter
- for(Iter it m.begin() it ! m.end() it)
- cout ltlt it-gtfirst ltlt " " ltlt it-gtsecond ltlt
endl
string name("ivan") int mark5 m.insert(make_p
air(name, mark))
112ostali asocijativni containeri
- dozvoljava duplicirane kljuceve
- zbog toga, dodatno podržava
- lower_bound(), upper_bound(), equal_range()
- drži samo kljuceve, moraju biti jedinstveni
- dozvoljava duplicirane kljuceve
11310. predavanje
- standardna biblioteka - algoritmi
114copy
- kopiranje preko iteratora
- vectorltintgt v(10)
- dequeltdoublegt d(v.size())
- copy(v.begin(), v.end(), d.begin())
- templateltclass InIt, class OutItgt inline
- OutIt copy(InIt p, InIt e, OutIt x)
- for ( p ! e p, x)
- x p
- return x
-
115copy - posebne primjene
- standarni iterator za ispis - ostream_iterator
- ostream_iteratorltintgt os(cout, "\n") // \n -
separator - vectorltintgt v(10)
- copy(v.begin(), v.end(), os)
- standarni iterator za unos - istream_iterator
istream_iteratorltintgt in(cin),
ends vectorltintgt v copy(in, ends,
back_inserter(v))
- ends - iterator sa default konstruktorom služi
kao oznaka kraja
- back_inserter() - funkcija koja vraca
back_insert_iterator
- back_insert_iterator - iterator koji radi
push_back() u operator()
116fill, generate - punjenje containera
typedef vectorltintgtiterator Iter vectorltintgt
v(10) for(Iter it v.begin() it ! v.end()
it) it -1
// isto kao fill(v.begin(), v.end(), -1)
typedef vectorltintgtiterator Iter vectorltintgt
v(10) for(Iter it v.begin() it ! v.end()
it) it rand()
// isto kao generate(v.begin(), v.end(), rand)
117funkcijski objekt
- klasa koja ima operator()
- za generate() - operator() nema argumenata,
vraca vrijednost
- class incr
- int n
- public
- incr(int initval0) n(initval)
- int operator()() return n
-
- int main()
- vectorltintgt v(10)
- generate(v.begin(), v.end(), incr())
118for_each, transform
- class avg
- int n double sum
- public
- avg() n(0), sum(0)
- void operator()(int elem) n sum elem
- operator double() return sum/n
-
- int main()
- istream_iteratorltintgt in(cin), ends
- vectorltintgt v
- copy(in, ends, back_inserter(v))
- cout ltlt "prosjek " ltlt for_each(v.begin(),
v.end(), avg())
- vracaju funkciju (funkcijski objekt)
- za transform() - operator() vraca novu
vrijednost
119count, find, replace, remove
- broj elemenata jednak nekoj vrijednosti
- cout ltlt "broj nula je " ltlt count(v.begin(),
v.end(), 0)
- prvi element koji je jednak nekoj vrijednosti
Iter it find(v.begin(), v.end(), 42) if(it !
v.end()) ... // nasao
- u stringu zamijeni sva slova 'a' sa 'e'
string s cin gtgt s replace(s.begin(), s.end(),
'a', 'e')
string s cin gtgt s s.erase(remove(s.begin(),
s.end(), 'a'), s.end())
- remove() ne briše nego vraca iterator - obavezan
poziv erase()
120predikat - count_if, find_if, ...
- predikat - operator() prima element, vraca bool
- primjer broj elemenata u vektoru manjih od 100
class less int limit public less(int
limit) limit(limit) bool operator()(int n)
return n lt limit ... int cnt
count_if(v.begin(), v.end(), less(100))
- koristeci standardni objekt
count_if(v.begin(), v.end(), bind2nd(lessltintgt(),
100))
121sort
- koristi operatorlt ili binarni predikat
- binarni predikat - operator() prima dva
elementa, vraca bool
- struct student
- string ime, prezime
- int ocjena
-
- struct comp
- bool operator() (const student s1, const
student s2) - return s1.ocjena lt s2.ocjena
-
-
- int main()
- vectorltstudentgt v
- // ... napuni container
- sort(v.begin(), v.end(), comp())
122podjela algoritama (potpuni spisak)
- nemodificirajuci na sekvenci for_each, find,
find_if, find_first_of, adjacent_find, count,
count_if, mismatch, equal, search, find_end,
search_n - modificirajuci na sekvenci transform, copy,
copy_backward, swap, iter_swap, swap_ranges,
replace, replace_if, replace_copy,
replace_copy_if, fill, fill_n, generate,
generate_n, remove, remove_if, remove_copy_if,
unique, unique_copy, reverse, reverse_copy,
rotate, rotate_copy - sortirane sekvence sort, stable_sort,
partial_sort, partial_sort_copy, nth_element,
lower_bound, upper_bound, equal_range,
binary_search, merge, inplace_merge, partition,
stable_partition - setovi includes, set_union, set_intersection,
set_difference, set_symmetric_difference - operacije na heap-u make_heap, push_heap,
pop_heap, sort_heap - min/max min, max, min_element, max_element,
lexicographical_compare - permutacije next_permutation, prev_permutation
- numericki acccumulate, inner_product,
partial_sum, adjacent_difference