You are on page 1of 99

Sveuilite u Zagrebu

Fakultet elektrotehnike i raunarstva


Zavod za telekomunikacije

C++
I
OSNOVE OBJEKTNO ORIJENTIRANOG
DIZAJNA
Predavanja

Marko Lackovi

Zagreb, 2002.

C++ i osnove objektno orijentiranog dizajna

Sadraj
1
2
3

Literatura................................................................................................................................7
Plan predavanja......................................................................................................................7
Osnovni tipovi podataka........................................................................................................8
3.1 Vrste podataka........................................................................................................................8
3.2 Identifikatori...........................................................................................................................8
3.3 Objekti i varijable...................................................................................................................9
3.4 Definicija (deklaracija) objekata ............................................................................................9
3.5 Ugraeni tipovi podataka .....................................................................................................10
3.6 Konstante..............................................................................................................................10
3.7 Brojevi..................................................................................................................................10
3.8 Sufiksi...................................................................................................................................11
3.9 Znakovi.................................................................................................................................11
3.10 Pretvorbe izmeu tipova. Cast operator.............................................................................12
3.11 Pobrojeni tipovi, identifikator typedef .............................................................................12
4
Operatori...............................................................................................................................14
4.1 Aritmetiki operatori ............................................................................................................14
4.2 Logiki operatori ..................................................................................................................14
4.3 Poredbeni operatori ..............................................................................................................15
4.4 Bitovni operatori i operator razdvajanja...............................................................................15
4.5 Hijerarhija operatora ............................................................................................................16
5
Naredbe za kontrolu toka programa..................................................................................17
5.1 Blokovi naredbi ....................................................................................................................17
5.2 Uvjetno grananje naredba naredba if ...............................................................................17
5.3 Uvjetni operator ? :.............................................................................................................18
5.4 Naredba switch ...................................................................................................................18
5.5 Petlja for ..............................................................................................................................19
5.6 Naredba while .....................................................................................................................19
5.7 Blok do while .....................................................................................................................20
5.8 Naredba continue continue ................................................................................................21
5.8.1 Znakovni niz..................................................................................................................23
5.8.2 Pridruivanje adrese pokazivau...................................................................................25
5.8.3 Aritmetika pokazivaa...................................................................................................25
5.8.4 Veza polja i pokazivaa.................................................................................................25
5.8.5 Dvodimenzionalna polja i pokazivai ...........................................................................25
5.8.6 Dinamika alokacija memorije, operator new ...............................................................25
5.8.7 Dinamika alokacija polja.............................................................................................26
5.9 Reference..............................................................................................................................26
6
Funkcije.................................................................................................................................27
6.1 Deklaracija funkcije .............................................................................................................27
6.2 Definicija funkcije................................................................................................................27
6.3 Argumenti funkcije ..............................................................................................................28
6.4 Argumenti funkcije (prijenos po vrijednosti).......................................................................28
6.5 Argumenti funkcije (prijenos kao pokaziva)......................................................................28
6.6 Argumenti funkcije (prijenos kao referenca) .......................................................................28
6.7 Polja kao argumenti funkcije................................................................................................29

C++ i osnove objektno orijentiranog dizajna


6.8 Podrazumijevani argumenti..................................................................................................29
6.9 Neodreeni argumenti ..........................................................................................................30
6.10 Pokazivai na funkcije .......................................................................................................30
6.11 Stog i rekurzija ...................................................................................................................30
6.12 Pokazivai i reference kao povratne vrijednosti ................................................................31
6.13 Globalni i statiki objekti ...................................................................................................31
7
Ulazni i izlazni tokovi...........................................................................................................32
7.1 to su ulazni i izlazni tokovi ................................................................................................32
7.2 Ispis pomou cout ...............................................................................................................32
7.3 Kontrola ispisa......................................................................................................................32
7.4 Uitavanje pomou cin........................................................................................................33
7.5 Uitavanje znakovnih nizova ...............................................................................................33
7.6 Datoteke i ulazno izlazni tokovi...........................................................................................34
7.6.1 itanje i pisanje iz/u datoteke .......................................................................................34
7.6.2 Modovi otvaranja datoteke............................................................................................34
7.6.3 Odreivanje i postavljanje poloaja unutar datoteke ....................................................35
7.6.4 Rad s datotekama (C) ....................................................................................................35
7.6.5 Rad s datotekama (C++)................................................................................................36
7.7 Primjeri zadataka..................................................................................................................36
8 Uvod u OOP..........................................................................................................................38
9
Enkapsulacija .......................................................................................................................39
9.1 Objekti i klase.......................................................................................................................39
9.2 Definicija klasa.....................................................................................................................39
9.3 Dodjela prava pristupa .........................................................................................................40
9.4 Prijateljske funkcije..............................................................................................................40
9.5 Umetnute (inline) funkcije...................................................................................................40
9.6 Deklaracija objekta...............................................................................................................41
9.7 Kljuna rije this ................................................................................................................41
9.8 Konstruktori .........................................................................................................................42
9.8.1 Podrazumjevani konstruktor .........................................................................................42
9.8.2 Konstruktor s parametrima............................................................................................42
9.8.3 Konstruktor kopije.........................................................................................................43
9.8.4 Destruktor......................................................................................................................43
9.9 Polja objekata .......................................................................................................................44
9.10 Statiki lanovi...................................................................................................................44
9.11 Pokazivai na podatkovne lanove klase ...........................................................................44
9.12 Pokazivai na funkcijske lanove klase .............................................................................45
9.13 Strukture .............................................................................................................................45
9.14 Unije ...................................................................................................................................45
9.15 Primjeri zadataka................................................................................................................46
10
Polimorfizam.....................................................................................................................49
10.1 to je polimorfizam............................................................................................................49
10.2 Preoptereenje funkcija ......................................................................................................49
10.3 Korisniki definirane konverzije........................................................................................50
10.3.1 Konverzija konstruktorom...........................................................................................50
10.3.2 Operator konverzije.....................................................................................................50
10.4 Preoptereenje operatora ....................................................................................................51
3

C++ i osnove objektno orijentiranog dizajna


10.4.1 Definicija operatorske funkcije ...................................................................................51
10.4.2 Operator = ....................................................................................................................52
10.4.3 Operator [] [] ..............................................................................................................53
10.4.4 Operator () () ..............................................................................................................53
10.4.5 Operator ->..................................................................................................................53
10.4.6 Prefiks i postfiks operatori ++ i -- ...........................................................................54
10.4.7 Operator umetanja << ..................................................................................................54
10.5 Primjeri zadataka................................................................................................................54
11
Nasljeivanje.....................................................................................................................58
11.1 to je nasljeivanje?...........................................................................................................58
11.2 Zadatak ...............................................................................................................................58
11.2.2 Sveoptika mrea s WDM...........................................................................................59
11.2.3 Optike komponente ...................................................................................................59
11.3 Prijenos znanja u C++ ........................................................................................................60
11.4 Odnosi meu komponentama (taksonomija)......................................................................61
11.5 Bazna klasa.........................................................................................................................61
11.6 Specificiranje nasljeivanja................................................................................................61
11.7 Nasljeivanje i prava pristupa ............................................................................................62
11.8 Nasljeivanje i relacije .......................................................................................................62
11.9 Viestruko nasljeivanje ....................................................................................................63
11.10 Virtualna osnovna klasa ...................................................................................................64
11.11 Karakteristike virtualnog nasljeivanja............................................................................64
11.12 Pristup lanovima izvedenih klasa ...................................................................................65
11.13 Ugraene pretvorbe i nasljeivanje..................................................................................65
11.14 Konstruktori i destruktori izvedenih klasa .......................................................................66
11.15 Podruje pretraivanja......................................................................................................66
11.16 Ugnijeeni tipovi ............................................................................................................67
11.17 Klase kao argumenti funkcija (ugraene konverzije) ......................................................67
11.17.1 Klase kao argumenti funkcija (korisnike konverzije) .............................................68
11.18 Nasljeivanje i preoptereeni operatori............................................................................68
11.19 Polimorfizam i tipovi vezivanja .......................................................................................68
11.20 Dinamiko povezivanje i virtualni funkcijski lanovi .....................................................69
11.21 Pozivi virtualnih funkcijskih lanova...............................................................................70
11.22 iste virtualne funkcije ....................................................................................................71
11.23 Virtualni destruktori .........................................................................................................71
11.24 Polimorfizam i proirivost koda.......................................................................................72
11.25 Primjeri zadataka..............................................................................................................73
11.25.1 Listing datoteke List.h ............................................................................................73
11.25.2 Listing datoteke List.cpp ........................................................................................74
12
Predloci (templates).........................................................................................................80
12.1 to su predloci (templates)?..............................................................................................80
12.2 Predloci funkcija...............................................................................................................80
12.2.1 Definicija predloka funkcije ......................................................................................80
12.2.2 Implicitno instanciranje predloaka ............................................................................81
12.2.3 Eksplicitno instanciranje predloaka...........................................................................81
12.2.4 Preoptereivanje predloaka funkcija .........................................................................82
12.3 Predloci klasa....................................................................................................................82
4

C++ i osnove objektno orijentiranog dizajna


12.3.1 Definicija predloka klase ...........................................................................................82
12.3.2 Instanciranje predloka klase i deklaracija objekta .....................................................83
12.3.3 Specijalizacija funkcijskih lanova .............................................................................83
12.3.4 Predloci, statiki lanovi i ugnjeivanje ..................................................................84
12.3.5 Predloci i prijatelji klasa ............................................................................................84
12.3.6 Predloci i nasljeivanje..............................................................................................84
12.4 Primjeri zadataka................................................................................................................85
13
Imenici (namespaces) ...................................................................................................88
13.1 to su imenici? ...................................................................................................................88
13.2 Deklaracija imenika............................................................................................................88
13.3 Pristup elementima imenika ...............................................................................................88
13.4 Deklaracija i direktiva using .............................................................................................89
13.5 Klase i deklaracija using ...................................................................................................89
14
Iznimke..............................................................................................................................90
14.1 to su iznimke? ..................................................................................................................90
14.2 Blokovi pokuaja i hvatanja iznimaka ...............................................................................90
14.3 Identifikacija iznimaka.......................................................................................................90
14.4 Tijek obrade iznimaka........................................................................................................91
14.5 Liste moguih iznimaka .....................................................................................................91
15
Pretprocesorske naredbe .................................................................................................92
15.1 Pojam pretprocesorskih naredbi .........................................................................................92
15.2 Naredbe #include, #define i #undef ...........................................................................92
15.3 Uvjetno prevoenje ............................................................................................................93
15.4 Uvjetno prevoenje, assert i pronalaenje pogreaka ....................................................93
15.5 Operatori za rukovanje nizovima .......................................................................................94
16
Organizacija koda ............................................................................................................95
16.1 Zato je organizacija koda potrebna...................................................................................95
16.2 Datoteke zaglavlja ..............................................................................................................95
16.3 Povezivanje ........................................................................................................................96
16.4 Specifikatori static i extern ...........................................................................................96
17
C i C++ ..............................................................................................................................97
17.1 Usporedba C i C++.............................................................................................................97
17.2 Slinost sintakse C i C++ ...................................................................................................97
17.3 Razlike sintakse C i C++....................................................................................................97
17.4 Novi mehanizmi u C++ ......................................................................................................98
17.5 Nove kljune rijei u C++ ..................................................................................................98
17.6 C++ kao objektno orijentirani jezik ...................................................................................99

C++ i osnove objektno orijentiranog dizajna

Language shapes the way we think,


and determines what we can think about.
B. L. Whorf (iz B. Stroustrup, "The C++ Programming Language")

C++ i osnove objektno orijentiranog dizajna

1 Literatura

H. Schildt: Turbo C++ for Windows Inside & Out, Osborne McGraw-Hill

brzi uvod u osnove C++-a za itatelje koji poznaju C sintaksu. Osnove C++ programiranja za
MS Windowse.

Boris Motik i Julijan ribar: Demistificirani C++, Element, Zagreb, 1997.

detaljan pregled C++ jezika uz opsean pregled C sintakse. Pristup objektno orjentiranom
dizajnu.

S. B. Lippman: C++ Primer, 2nd Edition , Addison-Wesley Publishing Company,


Reading, Massachusetts

sveobuhvatan prikaz C++ jezika uz kratak uvod u C sintaksu

B. Eckel: Thinking in C++, 2nd edition

(vrlo) detaljan pregled C i C++ jezika

M. A. Ellis, B. Stroustrup: The Annotated C++ Reference Manual, AddisonWesley Publishing Company, Reading, Massachusetts

C++ standard

R. B. Murray: C++ Strategies and Tactics, Addison-Wesley Publishing Company,


Reading, Massachusetts

napredniji pregled uporabe C++ jezika uz naglasak na objektno orjentiranom dizajnu

2 Plan predavanja
Teme obraene u predavanjima:
1. osnovni elementi prog. jezika C:

Osnovni tipovi podataka


Operatori
Naredbe za kontrolu toka programa
Polja, pokazivai i reference
Funkcije
Ulazni i izlazni tokovi

2. osnovni elementi prog. jezika C++


3. objektno orijentirani dizajn

C++ i osnove objektno orijentiranog dizajna

3 Osnovni tipovi podataka


Teme obraene u ovom dijelu:

Vrste podataka
Identifikatori
Objekti i varijable
Definicija (deklaracija) objekata
Ugraeni tipovi podataka
Konstante
Brojevi
Sufiksi
Znakovi
Pretvorbe izmeu tipova. Cast operator.
Pobrojeni tipovi, identifikator typedef

3.1 Vrste podataka


Program obavlja operacije nad nekim podacima. Podaci se mogu svrstati u dvije osnovne
skupine:

podaci s promjenjivom vrijednou (varijable), i

podaci s nepromjenjivom vrijednou (konstante).

Osnovna razlika izmeu ovih podataka lei samo u dozvoli pridruivanja njihove vrijednosti
kod konstanti je to mogue samo pri definiciji konstante (uvoenju simbolikog imena
identifikatora u prostor imena (scope)) dok je kod varijabli ta promjena mogua bilo gdje
unutar programa ali nakon definicije varijable
Navedena razlika vrijedi u veini programskih jezika, dok neki ipak ne razlikuju varijable od
konstanti, tj. dozvoljavaju pridruivanje vrijednosti samo jednom (npr. single assignment jezici
kao Erlang).

3.2 Identifikatori
Podacima se pristupa preko nekog imena koji se naziva identifikator:
int mojaVar; //mojaVar je identifikator

Identifikatori moraju potovati sljedea pravila:


1. identifikator moe sadravati slova (engleske) abecede, brojeve i znak za
podcrtavanje (poveznica, underscore _),
2. prvi znak identifikatora mora biti slovo ili poveznica, ui
3. identifikator ne smije biti jednak nekoj od kljunih rijei, ali kljuna rije moe biti dio
identifikatora:
mojaDoubleVarijabla

Identifikatori se obino piu malim slovima, za razliku od imena simbolikih konstanti koja se
(obino) piu velikim slovima:
8

C++ i osnove objektno orijentiranog dizajna


#define MAX 10 //konstanta imena MAX
int max; //varijabla s identifikatorom max

Za identifikator je najbolje odabrati mnemoniko ime koje e asocirati na svrhu njegove


uporabe u programu.
Identifikator koji se sastoji od vie rijei treba pisati uporabom poveznice ili velikih poetnih
slova rijei:
int indeks_polja; //C konvencija
int indeksPolja; //C++ konvencija

U ovim predavanjima biti e koritena iskljuivo C++ konvencija.

3.3 Objekti i varijable


Pod nazivom objekt se smatra dio memorije koji sadri podatke nekog tipa, a koji je dostupan
preko svog simbolikog imena (identifikatora). U C++ se pod nazivom objekt u uem smislu
misli na konkretnu realizaciju klase, a pod nazivom varijabla jednostavan objekt koji sadri samo
jedan tip podataka (jedan cijeli broj, znak, itd.).
Sa svakim objektom povezane su dvije vrijednosti:
1. vrijednost podatka (podataka) spremljenih na neku memorijsku lokaciju. Ova vrijednost
se esto naziva rvalue, i
2. poetna adresa memorije na kojoj je spremljen taj podatak (podaci). Ova vrijednost se
naziva lvalue.
Prije upotrebe objekta potrebno je rezervirati njegovo mjesto u memoriji. Definicija objekta je
rezervacija tog memorijskog prostora. Veliina prostora ovisiti e o tipu objekta. Deklaracija
objekta je uvoenje njegovog imena u prostor imena (scope), ali ne i njegovo zauzee u
memoriji. Definicija tog objekta mora se nalaziti na nekom drugom mjestu.
Razlika izmeu deklaracije i definicije objekata dolazi do izraaja samo kod nekih specijalnih
sluajeva (kao to je extern povezivanje objekta). Zato se umjesto definicije najee
upotrebljava rije deklaracija. Kod funkcija je ta razlika velika pa tamo nije mogue
upotrebljavati ove rijei kao sinonime.

3.4 Definicija (deklaracija) objekata


Najjednostavnija deklaracija se sastoji od tipa objekta (koji moe biti ugraeni ili korisniki) te
imena objekta:
tip_objekta imeObjekta;
int var; //int je ugraeni tip
moj_tip b; //moj_tip je korisniki tip

Deklaracijom objekta rezervira se njegov memorijski prostor ovisno o tipu:


Vrijednost podataka koju objekt sadri (rvalue) deklaracijom u pravilu nije odreena pa se na nju
ne treba oslanjati (iako C++ inicijalizira vrijednost varijabli na 0). U jednom bloku naredbi ne
smije se deklarirati vie objekata s istim imenom.
Prilikom deklaracije objekta mogue je provesti i njegovu inicijalizaciju:
double c=2.2; //inicijalizacija varijable pridruivanjem vrijednosti

C++ i osnove objektno orijentiranog dizajna


klasa obj1(1); //inicijalizacija objekta konstruktorom
klasa obj2=obj1; //inicijal. objekta pridruivanjem (copy konstruktor)

3.5 Ugraeni tipovi podataka


U C++ definirani su ugraeni tipovi podataka (memorijsko zauzee), te operacije nad njima
(pridruivanje, aritmetike operacije).
Pravila provjere tipa (type-checking rules) utvruju pogrene operacije nad tipom. Pravila
konverzije odreuju postupak u sluaju predaje pogrenog tipa operaciji (funkciji)
U tablici su dani ugraeni brojevni tipovi podataka:
Ugraeni tip
char
short int
int

Zauzee
(bytes)
1
2
2 (4)

long int

float

double

long double

10 (8)

memorije

Raspon vrijednosti

Tonost

-32768 do 32768
-32768 do 32768
(-2147483648
do
2147483647)
-2147483648
do
2147483647
-3.41038 do 3.4 1038
i 3.410-38 do 3.41038
1.710308 do 1.7 10308
i
1.710-308
do
1.710308
-1.1104932 do 3.4 104932 i 3.410-4932 do
1.1104932

7 dec. znamenki
15 dec. znamenki
18 dec. znamenki

Navoenjem kljune rijei unsigned ispred tipa ograniava se raspon vrijednosti samo na
pozitivne brojeve, pri emu se dodatni bit predznaka upotrebljava za proirenje raspona granice
cjelobrojnih tipova se mogu pronai u limits.h, a decimalnih tipova u values.h.

3.6 Konstante
Kljunom rijei const prije tipa objekta mogue je objekt uiniti konstantom:
const tip obj;

Time se prevoditelju naznauje da se vrijednost objekta ne smije promijeniti pri emu e svaki
pokuaj promjene uzrokovati greku vrijednost konstante mora se inicijalizirati pri deklaraciji:
const float pi=3.14;

Ime konstante definirane na ovaj nain postoji u simbolikoj tablici imena i mogue ga je
dohvatiti iz programa za simboliko lociranje pogreaka konstantu je mogue definirati i kao
simboliku konstantu pretprocesorskom naredbom #define:
#define PI 3.14

Ovo ime ne postoji u simbolikoj tablici imena i predstavlja loije rjeenje,

3.7 Brojevi
U C++ postoje dva osnovna tipa brojeva
1. cijeli brojevi (integers), i
2. brojevi s pominim zarezom (floating point).

10

C++ i osnove objektno orijentiranog dizajna


Unutar koda mogue je koristiti brojevne konstante za inicijalizaciju vrijednosti varijabli ili
eksplicitno navoenje vrijednosti unutar izraza.
Cjelobrojne konstante se mogu prikazati u sljedeim brojevnim sustavima:

dekadskom

int a=16;

oktalnom (navoenje brojke 0 ispred cjelobrojne konstante)

int a=020;

heksadekadskom (navoenje 0x ispred cjelobrojne konstante)

int a=0x10;

Brojevne konstante mogue je navoditi i u znanstvenoj notaciji (exp zapis):


float b=-1.6e-19; //ili -1.6E-19

Unutar broja nisu dozvoljene praznine (npr. izmeu predznaka i broja ili broja i e).

3.8 Sufiksi
Cijeli se brojevi tretiraju kao int vrijednosti to je mogue promijeniti u double dodavanjem
decimalne toke iza broja
1.

Realni se brojevi tretiraju kao double vrijednosti, to je mogue pretvoriti u float dodavanjem
slova f ili F iza konstante:
1.2f

Poveanje preciznosti postie se dodavanjem slova l ili L:


1.2l //long double

Ogranienje na pozitivne brojeve dodavanjem slova u ili U:


1.2u
Broj ispred sufiksa
cijeli
decimalni

Sufiks
L, l
U, u
F, f
L, l

Rezultirajui tip
int
long int
unsigned int
double
float
long double

3.9 Znakovi
Znakovi se pridruuju varijablama tipa char pri emu se navode izmeu jednostrukih
navodnika:
char a=a;

Za znakove koji se ne mogu prikazati na zaslonu koristi se poseban zapis (escape sequence):
char noviRed=\n;

Na znakove se mogu primjenjivati operatori usporeivanja i aritmetiki operatori pri emu se


znak pretvara u svoj cjelobrojni ekvivalent iz ASCII tablice:
char zn=A;

11

C++ i osnove objektno orijentiranog dizajna


zn++;
cout<<zn<<endl; //B
zn=zn+32;
cout<<zn<<endl; //b
znak
\n
\t
\v
\b
\r
\f
\a
\\
\?
\'
\"
\0
\yyy
\xyyy

znaenje
novi red
horizontalni tab
vertikalni tab
backspace
pomak na poetak reda
nova stranica
zvuni signal
backslash
upitnik
jednostruki navodnik
dvostruki navodnik
NULL znak
znak iji je kod zadan oktalno
znak iji je kod zadan heksadekadski

3.10 Pretvorbe izmeu tipova. Cast operator.


Definirane su uobiajene implicitne konverzije koje pretvaraju neki ugraeni tip podataka u drugi
ako je to potrebno (npr. funkcija kao argument oekuje float, a naveden je int).
Iste konverzije se primjenjuju pri obavljanju aritmetikih funkcija na dva razliita tipa (npr.
odreivanje tipa rezultata pri zbrajanju int i float).
Uobiajene su konverzije na jedan tip vie po zauzeu memorije. Operatorom dodjele tipa
(cast operatorom) mogue je eksplicitno dodijeliti tip konverzije brojevnoj konstanti ili
varijabli. Ciljni tip odreuje se navoenjem imena u zagradama ispred identifikatora varijable ili
broja:
float rez=(float)a / (float)b;

Dozvoljeno je koristiti i funkcijski oblik dodjele tipa:


float rez=float(a) / float(b);

Za specificiranje tipa konstante ee se koriste sufiksi.


Predani tip
char

int
long
float
double

Ugraene konverzije prema


int
long
float
(long) double
long
float
(long) double
float
(long) double
(long) double
long double

3.11 Pobrojeni tipovi, identifikator typedef

12

C++ i osnove objektno orijentiranog dizajna


Pobrojani tip (enumerated type) se koristi ako varijabla poprima vrijednost iz (malog) skupa
ogranienih vrijednosti:
enum godina {prva, druga, treca, cetvrta, peta};
godina trenutnaGod = cetvrta;

Vrijednost varijable pobrojanog tipa zamjenjuje se cijelim brojem koji ukazuje na poziciju
vrijednosti unutar liste (prvi element ima podrazumijevanu vrijednost 0):
cout<<trenutnaGod<<endl; //3

Moe se eksplicitno odrediti vrijednost indeksa prvog lana:


enum godina {prva = 1, druga, treca, cetvrta, peta};
godina trenutnaGod = cetvrta;
cout<<trenutnaGod<<endl; //4

Ako se navede deklaracija varijabli odmah iza definicije pobrojanog tipa, njegovo se ime moe i
ispustiti (osim ako se ne koristi dalje u programu):
enum {false=0, true} logicka;

Operatorom typedef uvodi se novo ime za ve postojei ugraeni ili korisniki tip podataka:
typedef poznati_tip novoIme;
typedef int cjelobrojni;
cjelobrojni a,b;

13

C++ i osnove objektno orijentiranog dizajna

4 Operatori
Teme obraene u ovom dijelu:

Aritmetiki operatori
Logiki operatori
Poredbeni operatori
Bitovni operatori i operator razdvajanja
Operatori pridruivanja
Hijerarhija operatora

4.1 Aritmetiki operatori


Unarni operatori se mogu primijeniti samo na jedan objekt, dok binarni operatori djeluju na dva
objekta.
tip operatora
unarni

binarni

primjena operatora nad


operandima
+x
-x
++x
--x
x++
x-x+y
x-y
x*y
x/y
x%y

znaenje
unarni plus
unarni minus
uveaj prije
umanji prije
uveaj nakon
umanji nakon
zbrajanje
oduzimanje
mnoenje
dijeljenje
modulo

Kod upotrebe prefiks operatora (++x, --x) prvo se varijabla uveava ili umanjuje, a zatim se
dohvaa njezina vrijednost. Kod upotrebe postfiks operatora (x++, x--) prvo se dohvaa
vrijednost varijable, a zatim se ona uveava ili umanjuje.
Ukoliko vrijednost varijable prekorai gornju doputenu granicu dolazi do brojanog
(numerikog) preljeva pri emu se gubi bit najvee teine koji vie ne stane u rezerviranu
memorijsku lokaciju:
int i=32767+1; //0

Prilikom obavljanja aritmetike operacije nad razliitim tipovima dolazi do ugraene konverzije
na zajedniki tip. Ukoliko su tipovi operanada jednaki ili se daju svesti na zajedniki tip obavlja
se aritmetika operacija nad tim tipom. Konverzija na tip varijable u koju se pohranjuje rezultat
vri se nakon izrauna rezultata:
float a=1/3;

daje rezultat 0, jer je rezultat cjelobrojnog dijeljenja 0 koja se tek pri pridruivanju
varijabli konvertira na float
double b=1/3.;

obavlja se double dijeljenje jer se broj 1 svodi na zajedniki tip double.

4.2 Logiki operatori


14

C++ i osnove objektno orijentiranog dizajna


Varijable ugraenog tipa bool mogu poprimiti logike vrijednosti true (ili broj 1) i false (ili
broj 0)
bool logicka=true;

Varijable tipa bool nisu dio C++ standarda (barem ne kod starijih standarda) tako da se ako
programer ima elju koristiti vrijednosti true i false preporua deklaracija pobrojenog tipa:
enum {false=0, true} mojBool;
mojBool logicka=true;

Time se osigurava sigurna portabilnost koda izmeu starijih i novijih prevoditelja


Logiki operator
x || y
x && y
!x

Znaenje
logiki ili
logiki i
logika negacija

Zamjenska oznaka
x or y
x and y
not x

4.3 Poredbeni operatori


Poredbeni operatori omoguuju usporedbu dva objekta pri emu se dobiva rezultat tipa bool ako
je uvjet usporedbe zadovoljen rezultat je true, inae false.
cout<< (1 < 2) <<endl; //1
char a=M;
int b=77;
cout<< (int)a!=b <<endl; //0
Poredbeni operator
x!=y
x==y
x>=y
x>y
x<=y
x<y

Znaenje
razliito
jednako
vee ili jednako
vee od
manje ili jednako
manje od

4.4 Bitovni operatori i operator razdvajanja


Bitovni operatori omoguuju izravne operacije nad bitovima.
Operator razdvajanja slui za razdvajanje izraza u naredbama, pri emu se oni izvode s lijeva na
desno:
int i;
i = 1 , i + 1; //varijabli i se prvo pridrui vrijednost 1, a zatim se ona
uvea za 1
unsigned int a=UINT_MAX;
int b=23;
cout<<b<<endl; //23
cout<<(b&a)<<endl; //23, a=0xffffffff (hex)
bitovni operator
znaenje
x>>n
posmak udesno
x<<n
posmak ulijevo
x ^ y
iskljuivi ili
x | y
binarni ili
x & y
binarni i
~x
komplement

2.5. Operatori pridruivanja


15

C++ i osnove objektno orijentiranog dizajna


Operator pridruivanja = objektu s lijeve strane pridruuje vrijednost izraza s desne strane.
Operatori obnavljajueg pridruivanja (update assignment) obavljaju zadanu operaciju izmeu
objekta s lijeve strane i vrijednosti izraza s desne strane.
Operatori obnavljajueg pridruivanja sastoje se od odgovarajueg operatora i znaka =
!= &= ^= <<= >>= %= /= *= -= += =

Operatori pridruivanja imaju manji prioritet od svih ostalih operatora (osim razdvajanja) tako da
uvijek dolazi do izraunavanja izraza s desne strane prije obavljanja odgovarajue operacije:
int a=1, b=2, c=3;
a+=b*c; //7

4.5 Hijerarhija operatora


znaenje

pridruivanje

::

operator

podruje (scope)

s desna na lijevo

->*

operator
.*

znaenje

pridruivanje

pokazivai na lan

s lijeva na desno

::

podruje (scope)

s lijeva na desno

* / %

mnoenja

s lijeva na desno

->

izbor lana

s lijeva na desno

+ -

zbrajanja

s lijeva na desno

[]

indeksiranje

s lijeva na desno

<<

bitovni posmak

s lijeva na desno

>>

()

poziv funkcije

s lijeva na desno

< > <=

poredbeni operatori

s lijeva na desno

++

uveaj nakon

s lijeva na desno

== !=

operatori jednakosti

s lijeva na desno

--

umanji nakon

s lijeva na desno

&

bitovni i

s lijeva na desno

sizeof

veliina objekta

s desna na lijevo

bitovno iskljuivo ili

s lijeva na desno

++

uveaj prije

s desna na lijevo

bitovni ili

s lijeva na desno

--

umanji prije

s desna na lijevo

&&

logiki i

s lijeva na desno

>=

* & + -

unarni operatori

s desna na lijevo

||

logiki ili

s lijeva na desno

new

stvori objekt

s desna na lijevo

?:

uvjetni izraz

s desna na lijevo

delete

izbrii objekt

s desna na lijevo

= *= /= += -= &=

pridruivanja

s desna na lijevo

typeid

tip objekta

s desna na lijevo

razdvajanje

s lijeva na desno

()

dodjela tipa

s desna na lijevo

:: imaju najvii

prioritet, a

, najnii

16

C++ i osnove objektno orijentiranog dizajna

5 Naredbe za kontrolu toka programa


Teme obraene u ovom dijelu:

Blokovi naredbi
Uvjetno grananje naredba if
Uvjetni operator ? :
Naredba switch
Petlja for
Naredba while
Blok do-while
Naredba break
Naredba continue

5.1 Blokovi naredbi


Tok programa nije linearan i ovisi o razliitim uvjetima dijelove programa koji se izvode uvjetno
ili se ponavljaju grupiraju se u blokove koji se tretiraju kao jedna logika cjelina ili jedna
naredba:
void main(void) {
int a;
{
cin>>a;
int b=a-3;
cout<<b<<endl;
}
cout<<b<<endl; //greka
}

Koritenjem naredbi za kontrolu toka programa mogue je uvjetovati izvoenje bloka (if-else
naredba), ponoviti izvoenje odreeni broj puta (for petlja) ili ponoviti izvoenje dok neki od
uvjeta nije zadovoljen (while-do, do-while petlje).
Varijable definirane unutar bloka vidljive su samo unutar njega, jer se tretiraju kao lokalne
varijable iji je domet (scope) jednak bloku unutar kojeg su definirane.

5.2 Uvjetno grananje naredba naredba if


Omoguava uvjetno grananje toka ovisno da li ispunjen uvjet
Opi oblik:
if ( uvjet1 ) false
{ blok 1 }
else if ( uvjet2 )
{ blok 2 }
else if ( uvjet3 )
{ blok 3 }
...
else
{ blok n }

Uvjeti predstavljaju logike izraze poput 5-6 > 0, a == b, itd.


Mogue je ugnjeivanje if naredbi.

17

C++ i osnove objektno orijentiranog dizajna


Na slici 1 prikazan je blok dijagram if-else naredbe.

Slika 1 Blok dijagram if-else naredbi

5.3 Uvjetni operator ?

Ne spada u naredbe za kontrolu toka programa, ali je po znaenju vrlo slian if-else bloku
Opi oblik:
uvjet ? izraz1 : izraz2 ;

Ako je logiki izraz uvjet istinit izvrava se izraz1, a u suprotnom izraz2.


Na slici 2 prikazan je blok dijagram ?: naredbe.

Slika 2 Blok dijagram ?: naredbe

5.4 Naredba switch


Ukoliko ispitivani izraz moe poprimiti vie razliitih vrijednosti, zbog preglednosti se umjesto
naredbe if koristi naredba switch.
Opi oblik:
switch ( cjelobrojni_izraz )
{
case konstantan_izraz_1 :
//prvi blok naredbi
break;
case konstantan_izraz_2 :
//drugi blok naredbi
break;
...
default:
//n-ti blok naredbi
}

Prvi korak je izraunavanje vrijednosti cjelobrojni_izraz, to moe biti rezultat aritmetikog


ili logikog izraza (4 > 2 zamjenjuje se s 1) jednakost uvjeta s nekim izrazom se ispituje
redoslijedom navoenja u programu. Ukoliko je jednakost ispunjena izvodi se slijed naredbi
18

C++ i osnove objektno orijentiranog dizajna


naveden iza : (ne upotrebljavaju se oznake {} bloka!). Nakon izvoenja odgovarajueg bloka
prelazi se na sljedei ispitivanje jednakosti sljedeeg uvjeta. Ako se eli osigurati prekid daljnjeg
ispitivanja nakon to je izveden odgovarajui blok koristi se naredba break na kraju bloka koja
uzrokuje prekid izvravanja naredbe switch. Ako cjelobrojni_izraz nije jednak ni jednom od
uvjeta izvodi se blok naredbi iza default naredbe. Navoenje default bloka nije obavezno.
Na slici 3 prikazan je blok dijagram switch naredbe.

Slika 3 Blok dijagram switch naredbe

5.5 Petlja for


Koristi se za ponavljanje bloka poznati broj puta
Opi oblik:
for (poetni_izraz ; uvjet_izvoenja ; izraz_prirasta ){
// blok naredbi
}
poetni_izraz je najee pridruivanje poetne vrijednosti brojaa. Rezultat ispitivanja
uvjet_izvoenja mora biti bool. Ako je rezultat ispitivanja istinit izvrava se blok naredbi i
izraunava izraz_prirasta (npr. poveanje brojaa). Ako je rezultat ispitivanja neistinit izlazi

se iz petlje.
Na slici 4 prikazan je blok dijagram for petlje.

Slika 4 Blok dijagram for petlje

5.6 Naredba while

19

C++ i osnove objektno orijentiranog dizajna


Koristi se za ponavljanje bloka iji broj ponavljanja nije poznat. Uuvjet izvoenja se ispituje prije
izvoenja bloka.
Opi oblik:
while ( uvjet_izvoenja ){
//blok naredbi
}

Ako je rezultat izraunavanja uvjet_izvoenja logika istina izvodi se blok_naredbi. Nakon


toga se ponavlja ispitivanje uvjeta. Ako je je rezultat izraunavanja uvjet_izvoenja logika
neistina preskae se blok_naredbi i nastavlja se izvoenje od prve naredbe iza bloka.
blok_naredbi utjee na uvjet_izvoenja (inae je petlja beskonana).
Na slici 5 prikazan je blok dijagram while petlje.

Slika 5 Blok dijagram while petlje

5.7 Blok do

while

Uvjet ponavljanja se ispituje nakon to je blok izvren blok se izvrava barem jedanput.
Opi oblik:
do{
//blok naredbi
}while ( uvjet_ponavljanja )

Na slici 6 prikazan je blok dijagram do while naredbe.

Slika 6 Blok dijagram do while petlje

3.8. Naredba break


Koristi se samo u petljama i switch naredbi uzrokuje prekid izvoenja tijela petlje i skok na prvu
sljedeu naredbu izvan petlje.
petlja {
naredba_1;

20

C++ i osnove objektno orijentiranog dizajna


naredba_2;
. . .
break;
. . .
naredba_n;
}
// naredbe iza bloka

Na slici 7 prikazan je blok dijagram naredbe break.

Slika 7 Blok dijagram naredbe break

5.8 Naredba continue continue


Koristi se u istim uvjetima kao i naredba break, ali uzrokuje skok na kraj petlje pri emu se petlja
ponovno izvrava.
petlja {
naredba_1;
naredba_2;
. . .
continue;
. . .
naredba_n;
}

Upotreba naredbi break i continue nije preporuljiva (osim u iznimnim sluajevima kao kod
naredbe switch), jer se time naruava strukturiranost programa.
Na slici 1 prikazan je blok dijagram naredbe continue.

Slika 8 Blok dijagram naredbe continue

4. Polja, pokazivai i reference 4. Polja, pokazivai i reference


Teme obraene u ovom dijelu:

Polja podataka
Definicija polja
Znakovni niz

21

C++ i osnove objektno orijentiranog dizajna


Operacije nad znakovnim nizovima
Pokazivai (pointeri)
Pridruivanje adrese pokazivau
Aritmetika pokazivaa
Veza polja i pokazivaa
Dvodimenzionalna polja i pokazivai
Dinamika alokacija memorije operator new
Dinamika alokacija polja
Reference
4.1. Polja podataka 4.1. Polja podataka
Struktura podataka koja se sastoji od konanog broja istovrsnih podataka (lanova polja) koji
dijele isto ime (identifikator polja). Svi podaci u polju moraju biti istog tipa direktan pristup
podacima preko indeksa koji moe biti nenegativan cijeli broj:
x[ind] (jednodimenzionalno polje)
y[ind1][ind2] (dvodimenzionalno polje)
z[ind1][ind2]. . . [indn] (n-dimenzionalno polje)

pri emu indeks pristupa ind moe biti jednak konstanti, varijabli ili nekom izrazu.
polje dimenzije n+1
polje dimenzije 2(n+1)

polje dimenzije (m+1)(n+1)

4.1.1. Definicija polja 4.1.1. Definicija polja


Statika definicija polja mora se obavezno navesti dimenzija polja u obliku cjelobrojne,
simbolike konstante ili fiksnog izraza:
int ia[5], aiHuge[MAX];
char text[LINE+1];
float sqMatrix[ROW][COL];

Tip polja moe biti bilo koji ugraeni ili izvedeni tip:
toBeOr notToBe[THAT][IS][THE][QUESTION];

Prilikom definicije mogue je i inicijalizirati lanove polja. U tom sluaju nije potrebno navoditi
dimenzije, jer se one odreuju prema inicijalizacijskoj listi:
int ia[] = {1,2,3,4,5}; //cjelobrojni niz od pet lanova

22

C++ i osnove objektno orijentiranog dizajna


float fa[][] = { //matrica 2x3
{1.1,2.2,3.4},
{2.1,3.2,1.3}
};
float[2][3] = {1.1,2.2,3.4,2.1,3.2,1.3} //isto kao i gore

Svi neinicijalizirani lanovi popunjaju se nulama.


Prvi lan polja ima indeks 0, dok je indeks zadnjeg lana polja jednak duljini polja umanjenoj za
1 (jednodimenzionalna polja). Dimenzije polja moraju biti poznate prilikom prevoenja
programa, te se ne mogu mijenjati tijekom izvoenja programa (statika definicija):
int n;
cout<<n;
float fa[n] ; //greka n nije poznat prilikom prevoenja

Prevodilac ne provjerava da li su indeksi polja unutar dimenzija polja mogue je pristupiti


memorijskoj adresi koja je izvan podruja rezerviranog za polje.
5.8.1 Znakovni niz
Deklaracija kao polje znakova
char znNiz[MAXZN+1];

Preporuljivo je da dimenzija char polja bude za 1 vea od broja znakova koje sadri, da bi se na
zadnje mjesto moglo postaviti oznaka kraja znakovnog niza (stringa) \0 ili 0 (NULL
character):
char znakovniNiz[4] = {C,+,+};
znakovniNiz[3]=0;

Drugi nain inicijalizacije:


char bestBuy[]=Lada;

Niz bestBuy sadri 5 znakova jer je ukljuena oznaka za kraj \0.


NULL character je vaan jer on oznaava zavretak znakovnog niza u memoriji to je
neophodan podatak za funkcije koje vre transformacije nad znakovnim nizovima.
Operacije nad znakovnim nizovima

Deklaracije funkcije koje obavljaju operacije nad znakovnim nizovima sadrane su u datoteci
string.h koja se u program ukljuuje kao
#include <string.h> ili #include <cstring>
char strcat( char *pocetak, const char *nastavak );

Nadovezuje niz nastavak na niz pocetak. Dodaje NULL znak na kraj niza.

char strncat(char *pocetak, const char *nastavak, size_t duljina);

Nadovezuje niz nastavak na niz pocetak u duljini od najvie duljina znakova. Dodaje
NULL znak na kraj niza.

const char *strchr( const char *niz, int znak );

Trai se prva pojava znaka znak. Ako nije pronaen vraa se NULL pokaziva.

int strcmp( const char *niz1, const char *niz2 );

23

C++ i osnove objektno orijentiranog dizajna

Aritmetiki usporeuje nizove niz1 i niz2 sve dok se ne doe do razliitog znaka. Vraa 0
ako su nizovi jednaki, >0 ako je niz1 vei, <0 ako je niz1 manji.

int strncmp( const char *niz1, const char *niz2, size_t duljina );

Jednaka usporedba kao i strcmp, ali u duljini od max duljina znakova

char *strcpy( char *odrediste, const char *izvornik );

Kopira sadraj niza izvornik u niz odrediste. Kopiranje se prekida nakon to je dosegnut
NULL znak (NULL znak se kopira).

char *strncpy( char *odrediste, const char *izvornik, size_t duljina );

Isto kao i strcpy ali se kopira najvie duljina znakova.

size_t strlen( const char *niz );

Vraa duljinu znakovnog niza niz (ne raunajui NULL znak).

const char *strpbrk( const char *niz, const char *znakovi );

Pretrauje niz niz do pojave prvog znaka iz niza znakovi. Vraa se pokaziva na taj znak
ili NULL pokaziva ako nije pronaen.

size_t strspn( const char *niz, const char *podniz );

Trai u nizu niz prvi znak koji se ne pojavljuje u nizu podniz. Vraa pokaziva na taj znak
ili NULL pokaziva ako nije pronaen.

const char *strstr( const char *niz, const char *podniz );

Trai prvu pojavu niza podniz u nizu niz. Vraa pokaziva na mjesto prve pojave podniza
ili NULL pokaziva ako podniz nije pronaen.

const char *strchr( const char *niz, int znak );

Pretrauje niz niz i trai zadnju pojavu znaka znak. Vraa pokaziva na taj znak ili NULL
pokaziva ako znak nije pronaen.

char *strtok( char *niz, const char *granicnici );

Pretrauje niz niz i razbija ga na podnizove razdvojene nekim od znakova iz niza


granicnici. Vraa pokaziva na poetak sljedeeg podniza ili NULL pokaziva ako takav
podniz ne postoji.

4.2. Pokazivai (pointeri)


Objekti koji pokazuju na drugi objekt tako to sadre njegovu memorijsku adresu veliina svakog
pokazivaa je 4 bytea koliko je dovoljno za spremanje adresibilne memorijske lokacije.
Definicija pokazivaa:
tip *pokazivac; //*pokazivac moe pokazivati na tip tip

Pokaziva koji je samo definiran ne pokazuje ni na to time je rezervirano samo mjesto u


memoriji na koje e se spremiti adresa postojeeg objekta mogu pokazivati na bilo koji ugraeni
ili korisniki tip podataka:
int *intP;
char *charP;
mojTip *mojTipP;

Operator * naziva se operatorom dereferenciranja (indirekcije)


24

C++ i osnove objektno orijentiranog dizajna


5.8.2 Pridruivanje adrese pokazivau
Prilikom definicije pokazivau je mogue pridruiti adresu (postojeeg) objekta istog tipa. Isto je
mogue uiniti bilo gdje u kodu programa:
int a=5;

Operator & naziva se operatorom adrese i vraa adresu objekta u memoriji


int *pa1 = &a, *pa2;
...
pa2 = &a;
*pa1=1;
*pa2=2;

5.8.3 Aritmetika pokazivaa


Pokaziva sadri adresu objekta u memoriji:
int a=1, b=2; //objekt a je na mem. adresi 1000 byte, a objekt b na 1002 byte
int *pa=&a;
cout<<pa; //adresa objekta na kojeg pokazuje - 1000
cout<<*pa; //vrijednost objekta na kojeg pokazuje 1

Poveanje pokazivaa za 1 znai da on mora pokazivati na sljedei objekt tog tipa u memoriji to
znai uveanje adrese za veliinu tipa (char 1 byte, int 2 byte, float 4 byte, double 8 byte):
pa++; //uveanje adrese za veliinu tipa
cout<<pa; //1002
cout<<*pa; //ispis sadraja varijable b, jer su objekti a i b sukcesivni u
memoriji

5.8.4 Veza polja i pokazivaa


lanovi polja dohvaaju se preko pokazivaa, pri emu samo ime polja ima smisao pokazivaa
na prvi lan polja:
int ia[]={1,2,3,4,5};
cout<<*ia; //1
cout<<*(ia+2); //3
cout<<ia[2]; //3

Prilikom deklaracije polja ne dolazi do stvaranja pokazivaa u memoriji ime polja je samo
sinonim za pokaziva, tj. moe se koristiti kao pokaziva
5.8.5 Dvodimenzionalna polja i pokazivai
Dvodimenzionalno polje se moe shvatiti kao jednodimenzionalni niz jednodimenzionalnih
polja:
int ia[][]={{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}
ia[0], ia[1] i ia[2] se tretiraju kao pokazivai na prvi lan u recima 1, 2 i 3 i u ovom

sluaju vrijedi aritmetika nad pokazivaima:


cout<<*(ia[2]+2) //11

5.8.6 Dinamika alokacija memorije, operator new


Operatorom new rezervira se memorijski prostor za objekt nekog ugraenog ili korisnikog tipa.
Moe se rezervirati prostor i za strukture kao npr. polja povratna vrijednost je poetna adresa
memorijskog prostora rezerviranog za objekt ili NULL ako rezervacija memorije nije uspjela:
int *pok=new int(2);

Pokaziva pok pokazuje na novostvoreni objekt tipa int koji je inicijaliziran na vrijednost 2.
25

C++ i osnove objektno orijentiranog dizajna


if (!pok) exit(1);

provjera da li je alokacija memorije uspjela

Objekt stvoren operatorom new predstavlja dinamiki objekt, te ne spada u automatske objekte,
tj. nee biti uniten izlaskom iz bloka u kojem je deklariran dealokaciju memorije koju zauzima
objekt stvoren na ovaj nain mora obaviti programer operatorom delete i navoenjem poetne
adrese memorije koju taj objekt zauzima:
delete pok;

Dinamikim objektima pristupa se iskljuivo koritenjem pokazivaa


5.8.7 Dinamika alokacija polja
Omoguava da se stvori polje objekata tijekom izvravanja programa, tj. da njegove dimenzije
budu odreene vrijednostima koje nisu poznate pri prevoenju programa:
int n;
cin>>n;
float *fa=new float[n];

Oslobaanje zauzete memorije obavlja se koritenjem operatora delete:


delete [] fa;

Mogue je alocirati i viedimenzionalno polje, no sve dimenzije osim prve moraju biti poznate
pri prevoenju:
int **a;
a=new int*[3]; //polje tri int pokazivaa
a[0]=new int[2]; a[1]=new int[3]; a[2]=new int[5]; //svaki pokaziva pokazuje
na novo jednodimenzionalno int polje
int (*b)[3]=new int[n][3];
delete [] b;

5.9 Reference
Poseban tip podataka slian pokazivaima predstavljaju drugo ime za objekt odreenog tipa
te se nazivaju i aliasima prilikom deklaracije moraju biti inicijalizirane:
int a=1;
int &ref=a; //varijabli a se moe pristupiti preko imena a i ref
a=2;
ref=3;

Operator & se stoga naziva i operatorom referenciranja.

26

C++ i osnove objektno orijentiranog dizajna

6 Funkcije
Teme obraene u ovom dijelu:

Deklaracija funkcije
Definicija funkcije
Argumenti funkcije
Argumenti funkcije (prijenos po vrijednosti)
Argumenti funkcije (prijenos kao pokaziva)
Argumenti funkcije (prijenos kao referenca)
Polja kao argumenti funkcije
Podrazumijevani argumenti
Neodreeni argumenti
Pokazivai na funkcije
Stog i rekurzija
Pokazivai i reference kao povratne vrijednosti
Globalni i statiki objekti

6.1 Deklaracija funkcije


Funkcija je korisniki definirana operacija koja je predstavljena imenom deklaracija funkcije
sadri ime funkcije, listu argumenata koji predstavljaju ulazno-izlazni tok podataka u funkciju te
povratni tip koji predstavlja izlazni tip podataka:
<povratni_tip> ime_funkcije (<tip1> arg1, <tip2> arg2,);

Deklaracija funkcije ne opisuje to funkcija radi, ona daje samo prototip funkcije naziv
argumenata moe se ispustiti-kod deklaracije bitan je tip argumenata:
int f1(int a, float b);
int f2(int, float);

Mogue je deklarirati funkcije s neodreenim brojem argumenata broj, tip i poredak argumenata
odreuju potpis funkcije (funkcije f1 i f2 imaju jednake potpise) svaka funkcija mora biti
deklarirana u izvornom kodu prije koritenja (ovo ne mora biti zadovoljeno u C-u).

6.2 Definicija funkcije


Definicija funkcije sadrava uz naziv, povratni tip i listu argumenata tijelo funkcije, tj.
programski kod koji opisuje to funkcija radi:
int neg(int a){
return a;
}

Kljuna rije return obavlja prijenos povratne vrijednosti na mjesto poziva. Izmeu povratnog
tipa funkcije i tipa povratne vrijednosti obavlja se ugraena ili korisnika konverzija ako je
potrebno. Broj, poredak i tip argumenata u pozivu, definiciji i deklaraciji funkcije moraju biti
jednaki.
Definicija funkcije je ujedno i njezina deklaracija, te nije dozvoljeno deklarirati funkciju nakon
definicije. Deklaracija i definicija funkcije ne moraju biti u istoj datoteci. Definicija funkcije slui
prevodiocu da bi mogao obaviti strogu sintaksnu provjeru pri pozivu funkcije.
27

C++ i osnove objektno orijentiranog dizajna


Poveziva e omoguiti izvravanje funkcije pronalaskom njezine definicije ukoliko ona nije u
istoj datoteci kao i poziv funkcije.

6.3 Argumenti funkcije


Argument u definiciji funkcije zove se formalni argument funkcije i postoji samo unutar tijela
funkcije:
int f( int a ){ //a je formalni argument funkcije

return a;
}

Pri pozivu funkcije formalni argument zamjenjuje se stvarnim argumentom, tj. stvarnom
vrijednou:
int b=3;
f(b); //b je stvarni argument funkcije

Funkcije bez argumenata:


int f(){ //u C++ isto to i int f(void)

return 1;
}

6.4 Argumenti funkcije (prijenos po vrijednosti)


Kod prijenosa po vrijednosti (call by value) formalni i stvarni argument nisu meusobno
povezani unutar tijela funkcije se stvara interna kopija prenesenog objekta. Promjene nad
kopijom objektom unutar funkcije nisu vidljive izvan nje, tj. objekt u pozivajuem kodu ostaje
nepromijenjen:
int f(int a){ //argument se prenosi po vrijednosti
a++; //a je lokalna kopija stvarnog argumenta
return a;
}
int b=1;
int c=f(b);
cout<<b<<endl; //1 nema promjene u pozivajuem kodu
cout<<c<<endl; //2 promjena se u pozivajui kod prenijela preko povratne
vrijednosti

6.5 Argumenti funkcije (prijenos kao pokaziva)


Pri prijenosu kao pokazivaa promjene nad formalnim parametrima se odraavaju na stvarne
parametre jer se umjesto stvaranja kopije objekata koristi memorijska adresa stvarnog parametra:
int f(int *a){ //argument se prenosi kao pokaziva
(*a)++; //a je lokalna kopija prenesene adrese, no *a pokazuje na istu
lokaciju kao i stvarni argument
return (*a);
}
int b=1;
int c=f(&b); //potrebno je prenijeti adresu objekta
cout<<b<<endl; //2 promjena u pozivajuem kodu
cout<<c<<endl; //2

Prilikom prijenosa kao pokaziva ne postoji ugraena konverzija pa tipovi argumenata moraju
tono odgovarati

6.6 Argumenti funkcije (prijenos kao referenca)


28

C++ i osnove objektno orijentiranog dizajna


Prijenos argumenta kao reference ima isti efekt kao i prijenos argumenta kao pokaziva:
int f(int &a){ //argument se prenosi kao referenca
a++;
return a;
}
a se koristi kao normalna varijabla, no ona predstavlja drugo ime za stvarni parametar, a ne

njegovu kopiju
int b=1;
int c=f(b); //nije potrebno eksplicitno naglasiti prijenos adrese
cout<<b<<endl; //2 promjena u pozivajuem kodu
cout<<c<<endl; //2

6.7 Polja kao argumenti funkcije


Jednodimenzionalna polja (nizovi) se u funkciju prenose kao pokazivai jer je ime polja
sinonim za pokaziva na prvi lan polja. Sljedee deklaracije su stoga jednake:
void f1(int polje[]);
void f2(int *polje);

I u jednu i u drugu funkciju se moe predati polje kao argument:


int p[10];
f1(p[]);
f2(p);

U funkciju nije mogue prenijeti viedimenzionalna polja ije su dimenzije poznate prilikom
prevoenja, jer se kao nepoznata moe ostaviti tek prva dimenzija:
void f3(int polje[][10]); //argument je polje s proizvoljnim brojem
redaka, ali fiksnim brojem stupaca

Problem prijenosa dvodimenzionalnih polja (matrica) rjeava se prijenosom polja kao niza
jednodimenzionalnih polja (redaka) koji su u memoriji smjeteni jedan iza drugog. Elementu
polje[i][j] je mogue pristupiti i kao
polje[i*brStupaca+j] odnosno *(polje + i*brStupaca+j):
void f4(int *polje, int r, int s){
for(int i=0; i<r;i++){
for(int j=0;j<s;j++) cout<<polje(i*s+j)<<endl;
}
}

6.8 Podrazumijevani argumenti


Podrazumijevana vrijednost argumenta navodi se u deklaraciji funkcije:
int f (int a, int b=1){ //argument b ima podrazumijevanu vrijednost 1

Funkcija f se moe pozvati navoenjem oba argumenta, ili isputanjem drugog argumenta pri
emu se on zamjenjuje podrazumijevanom vrijednou:
f(3,1);
f(3); //ekvivalentni pozivi funkcije f

Podrazumijevana vrijednost se ne smije navesti u definiciji, ako su deklaracija i definicija


odvojene argumenti s podrazumijevanom vrijednou moraju se nalaziti na kraju liste
argumenata.

29

C++ i osnove objektno orijentiranog dizajna

6.9 Neodreeni argumenti


Navoenje neodreenog argumenta znai da se funkcija moe pozvati sa proizvoljnim brojem
argumenata proizvoljnog tipa, uz one koji su eksplicitno navedeni (potpis funkcije se ne
provjerava):
float f(int a, ){
}

Pri pozivu funkcije f obavezno je navesti jedan parametar tipa int (ili tipa koji ima konverziju na
int), te proizvoljan broj drugih parametara:
f(3);
f(5,e,C++,89.3);
f(C++); //greka nedostaje argument tipa int

Argumentima funkcije mogue je pristupiti koritenjem funkcija iz standardne stdarg.h


datoteke.

6.10 Pokazivai na funkcije


Kao argument funkcije mogue je prenijeti i adresu funkcije, odnosno navesti formalni argument
kao pokaziva funkcije formalni argument mora sadravati povratni tip i argument funkcije:
povratni_tip *f(tip1, tip2,)

Primjer:
int f1(int, double);
int f2(double, int);
float f3(int *f(int, double), float b){}
void main(){
f3(f1, 6);//samo ime fun. bez zagrada sinonim je za pok. na nju
f3(f2,6); //grekaarg. preneseni fun. ne odgovaraju deklaraciji
}

6.11 Stog i rekurzija


Pri svakom pozivu funkcije povratna adresa, lokalni objekti i argumenti spremaju se na sustavski
stog.
int f(int a){
int b=a-1;
return b;
}

Uestali pozivi i prenoenje po vrijednosti glomaznih struktura (velika polja i klase) znatno
optereuju stog i usporavaju izvravanje programa, te mogu dovesti do iscrpljenja raunalnih
memorijskih resursa.
Rekurzije zbog svog uestalog pozivanja funkcija nisu dobro rjeenje, te ih treba izbjegavati kad
god je mogue problem (jednostavno) sekvencijalno rijeiti
stog
lokalni objekt b (0)
lokalna kopija a stvarnog parametra (1)
povratna adresa (0xFF3A)

30

C++ i osnove objektno orijentiranog dizajna

void main(){
int c=f(1);
}

6.12 Pokazivai i reference kao povratne vrijednosti


Pokaziva kao povratna vrijednost:
tip *f(tip arg1, tip arg2, ){
...
return adresa;
}

Povratna adresa pri tome nikada ne smije pokazivati na automatski lokalni objekt, jer se takvi
objekti unitavaju pri izlasku iz funkcije.
Referenca kao povratna vrijednost:
tip &f(tip arg1, tip arg2, ){

return objekt;
}

Ako je povratni tip referenca nije potrebno eksplicitno navoditi da se u pozivajui kod vraa
adresa. Ovdje vrijedi ista napomena kao i kod vraanja pokazivaa.

6.13 Globalni i statiki objekti


Globalni objekti su objekti definirani izvan funkcije (ukljuujui i funkciju main()), te su vidljivi
u svim funkcijama ije definicije slijede:
int globalni;
int jaGaVidim (int, float);
void *jaIsto (double);
void main(void){

Promjene nad globalnim objektima vidljive su u svim funkcijama koje ga koriste globalni objekti
naruavaju principe dobrog strukturiranog programiranja. Statiki lokalni objekti inicijaliziraju se
samo jednom prilikom prevoenja, te se ne unitavaju pri izlasku iz funkcije. Statiki se objekti
deklariraju kljunom rijei static i tipom:
int brojilo(int prviPoziv){
static int brojac=0; //statika varijabla tipa int ija
brojac++; //se inicijalizacija se provodi samo jednom
}

31

C++ i osnove objektno orijentiranog dizajna

7 Ulazni i izlazni tokovi


Teme obraene u ovom dijelu:

to su ulazni i izlazni tokovi


Ispis pomou cout
Kontrola ispisa
Uitavanje pomou cin
Uitavanje znakovnih nizova
Datoteke i ulazno-izlazni tokovi
itanje i pisanje iz/u datoteke (C i C++)
Modovi otvaranja datoteke
dreivanje i postavljanje poloaja unutar datoteke

7.1 to su ulazni i izlazni tokovi


Ulazni i izlazni tokovi omoguavaju ulazno-izlaznu komunikaciju programa s vanjskim
jedinicama (zaslon, pisa, datoteka).
Jezik C++ ne definira ulazno-izlazne tokove, ve se koriste klase definirane u standardnoj
biblioteci iostream.h. Pokretanjem svakog C++ programa koji ima ukljuenu datoteku
iostream.h stvaraju se i inicijaliziraju 4 objekta:
cin obrauje unos sa standardne ulazne jedinice (tipkovnica)
cout obrauje ispis na standardnu izlaznu jedinicu (zaslon)
cerr obrauje ispis na standardnu izlaznu jedinicu za ispis pogreaka (zaslon)
clog obrauje ispis pogreaka s meupohranjivanjem

Stanje toka:
eof() vraa true ako je s toka vraen znak za kraj datoteke
bad() vraa true ako operacija nije uspjela zbog nepopravljive greke
fail() vraa true ako operacija nije uspjeno obavljena zbog bilo kojeg razloga
good() vraa true ako ni jedan od gornjih uvjeta nije true

7.2 Ispis pomou cout


Objekt cout usmjerava ispis podataka na zaslon pomou operatora << koji se naziva operatorom
umetanja (insertion operator). S desne strane operatora umetanja se moe nai bilo koji tip
podataka (char, short, int, long int, char *, float, double, long double, void
*):
cout<<C++<<endl; //endl je znak za kraj reda
cout<<3879<<endl;
int a=5;
cout<<a<<endl;

Mogue je ulanavanje ispisa:


cout<<Iz ovoga cu sigurno imati <<a<<.<<endl;

7.3 Kontrola ispisa

32

C++ i osnove objektno orijentiranog dizajna


Funkcijom width odreuje se irina ispisa:
cout.width(10); //podeena irina traje jedan ispis

Funkcijom fill odreuje se znak kojim e se popuniti praznine pri ispisu:


cout.fill(*); //postavljeni znak ostaje do sljedee promjene

Zastavice za formatiranje ispisa omoguuju precizno odreivanje izgleda ispisa:


cout.setf(ios::zastavica);
Zastavica
Znaenje
uppercase
zamjena malih slova velikim
showbase
ispis baze kao prefiksa
showpoint
ispis dec. toke za realne brojeve
showpos
forsira ispis predznaka +
scientific
ispis brojeva u exp notaciji
fixed
ispis brojeva s fiksnom dec. tokom
dec/hex/oct pretvorba u dekadsku/hex/oct bazu
internal
predznak lijevo, ostatak desno
left/right
poravnavanje ulijevo/udesno

7.4 Uitavanje pomou cin


Uitavanje se obavlja pomou objekta cin i ulaznog operatora >> koji se zove operator
izluivanja. S desne strane operatora izluivanja mogu se nai isti tipovi kao i kod operatora
umetanja:
int i; double d;
cin>>i; cin>>d;

Dozvoljeno je ulanavanje naredbi za uitavanje (redoslijed uitavanja s lijeva na desno):


int prvi; double drugi; float treci;
cin>>prvi>>drugi>>treci;

Praznina, tabulator i znak za novi red predstavljaju standardne graninike koji se ignoriraju, a
uitavanje u sljedeu varijablu se nastavlja gdje je prethodno uitavanje prekinuto.

7.5 Uitavanje znakovnih nizova


Za uitavanje znakovnih nizova mogu se koristiti sljedee funkcije:
get(char &znak);

Uitava jedan znak s ulaznog toka i pohranjuje ga u varijablu znak. Nakon to se uita znak za
kraj datoteke tok se postavlja u stanje eofbit.
char niz[100]; int i=0;
while (cin.get(niz[i]))
if(niz[i++]==\n) break;
niz[i-1]=\0;
get();

Uitava jedan znak s ulaznog toka te vraa kod uitanog znaka. Nakon to uita znak za kraj
datoteke vraa vrijednost 1.
while (niz[i]=cin.get())
if(niz[i++]==\n) break;
niz[i-1]=\0;
get(char *znNiz, int duljina, char granicnik=\n);

33

C++ i osnove objektno orijentiranog dizajna


Uitava niz znakova do najvie duljina-1 znakova ili do nailaska na znak graninik ili EOF.
Uitani niz pohranjuje u znNiz pri emu na kraj dodaje NULL znak. Ostavlja znak \n na toku.
cin.get(niz, sizeof(niz));

7.6 Datoteke i ulazno izlazni tokovi


Za rad s datotekama programer mora sam stvoriti objekt (ulazni ili izlazni tok) i vezati ga na
datoteku. Za rad s datotekama definirane su tri klase:

ifstream uitavanje podataka iz datoteke,

ofstream upis podataka u datoteku, i

fstream omoguuje i upis i itanje podataka.

Sve tri klase deklarirane su u fstream.h koja sadri i ostream.h pa ju nije potrebno zasebno
navoditi. Svaka operacija s datotekama sastoji se od tri dijela:

otvaranje datoteke,

ispis ili uitavanje podataka, i

zatvaranje datoteke.

7.6.1 itanje i pisanje iz/u datoteke


Prvo je potrebno inicijalizirati tok otvaranjem datoteke, za to se koristi klasa ifstream (itanje)
odnosno ofstream (pisanje) iji su konstruktori:
ifstream (char *ime_datoteke, openmode mod=in);
ofstream (char *ime_datoteke, openmode mod=out);

Otvaranje datoteke moe se obaviti pri deklaraciji objekta:


ifstream dat(ime_datoteke,ios::mod);
ofstream dat(ime_datoteke,ios::mod);

Datoteku je mogue otvoriti i nakon deklaracije objekta:


ifstream datUlaz;
ofstream datIzlaz;
datUlaz.open(ime_datoteke,ios::mod);
datIzlaz.open(ime_datoteke,ios::mod);

Nakon obavljenih operacija datoteka se mora zatvoriti funkcijskim lanom close():


datUlaz.close();
datIzlaz.close();

7.6.2 Modovi otvaranja datoteke


Prilikom otvaranja datoteke mogue je navesti opcije vezane uz njezino postojanje, nain itanja i
upisivanja:
Pri otvaranju moe se navesti vie modova:
Mod
app
ate
binary
in
nocreate

Znaenje
upis na kraj datoteke (append)
datoteka se otvara i skae se na kraj
upis i uitavanje u binarnom modu
otvaranje za itanje
pogreka ako datoteka ne postoji

34

C++ i osnove objektno orijentiranog dizajna


noreplace
out
trunc

pogreka ako datoteka postoji


datoteka se otvara za pisanje
sadraj datoteke se brie prilikom otvaranja

ofstream dat(ime_datoteke,ios::mod1|ios::mod1);

datoteku je mogue otvoriti i za itanje i pisanje koritenjem klase fstream:


fstream datUI(ime_datoteke,ios::in|ios::out|ios::mod);

7.6.3 Odreivanje i postavljanje poloaja unutar datoteke


Pokaziva datoteke (file pointer) pokazuje na poziciju u datoteci na kojoj se operacija obavlja, te
je jednak udaljenosti pozicije u byteovima od poetka datoteke.
U klasi ostream postoje dva funkcijska lana koja dohvaaju pokaziva datoteke:

tellp() vraa trenutnu vrijednost pokazivaa datoteke, i

seekp() pomie se na zadani poloaj unutar datoteke.

Analogne funkcije tellg() i seekg() postoje u klasi istream. Ove funkcije deklarirane su kao:
ostream
istream
ostream
istream

&ostream::seekp(streampos
&istream::seekg(streampos
&ostream::seekp(streamoff
&istream::seekg(streamoff

&pozicija);
&pozicija);
&pomak, ios::seekdir smjer);
&pomak, ios::seekdir smjer);

Prve dvije inaice prihvaaju apsolutnu vrijednost pozicije u oktetima, dok druge dvije prihvaaju
relativnu vrijednost pomaka u oktetima u odnosu na pobrojenje seekdir koje moe poprimiti
vrijednosti:
seekdir vrijednost
beg
cur
end

znaenje
pomak u odnosu na poetak datoteke
pomak u odnosu na trenutnu poziciju u datoteci
pomak u odnosu na kraj datoteke

7.6.4 Rad s datotekama (C)


Suelje prema datoteci pomou file pointera:
FILE *f;

Otvaranje datoteke:
f=fopen(ime_datoteke,nain_otvaranja);

Naini otvaranja:
Oznaka
r
w
w+
r+
a+

Znaenje
itanje
pisanje, ako datoteka postoji brie se
itanje + pisanje, datoteka se stvara ako ne postoji
itanje + pisanje, datoteka mora postojati
itanje + pisanjena kraj datoteke

Pisanje u datoteku

int fprintf( FILE *f, const char *format [, argument ]...);


int fputs( const char *string, FILE *stream );

iz datoteke se ita dok se ne naie na znak za novi red, kraj datoteke ili se ne proita n-1
znak

itanje iz datoteke

35

C++ i osnove objektno orijentiranog dizajna


int fscanf( FILE *f, const char *format [, argument ]... );
char *fgets( char *string, int n, FILE *stream );

ako se proita znak za novi red, ukljuuje se u string

Primjer:
FILE* f=fopen(mojaDat.txt,w+);
char* str=new char[10];strcpy(str,c++);
fprintf(f,%s,str);
fscanf(f,%s,str);
fclose(f);

Primjer:
FILE* f=fopen(mojaDat.txt,w+);
char* str=new char[10];strcpy(str,c++);
fputs(abc,f);
fscanf(f,10,str);
fclose(f);

7.6.5 Rad s datotekama (C++)


Pisanje u datoteku

basic_ostream& put(E c);


objekt tipa ofstream/fstream << podaci

itanje iz datoteke
basic_istream& get(basic_streambuf<E, T> *sb);
basic_istream& get(basic_streambuf<E, T> *sb, E delim);
objekt tipa ifstream/fstream >> podaci

Primjer:
ifstream datUlaz; datUlaz.open(dat1.txt,ios::in);
ofstream datIzlaz; datIzlaz.open(dat2.txt,ios::out);
char c;
while(datUlaz.get(c)!=EOF) datIzlaz.put(c);
datUlaz.close(); datIzlaz.close();

Primjer:
ifstream datUlaz; datUlaz.open(dat1.txt,ios::in);
char c[50];
datUlaz >> c;
cout<<c;
datUlaz.close();

7.7 Primjeri zadataka


Zadaci u ovom poglavlju odnose se na sva predhodno obraena podruja.
1.
Proitajte niz rijei sa standardnog ulaza. Rije "kraj" slui kao oznaka za kraj unosa.
Nakon to je unesena rije "kraj" ispiite uitane rijei u redoslijedu u kojem su uitane, i
sortirane po abecedi.
Uputa: Koristite funkcije. Koristite globalne varijable gdje je potrebno.
2.
Uitajte reenicu sa standardnog ulaza (reenica zavrava s tokom to je oznaka za kraj
unosa). Ispiite statistiku reenice (broj rijei, broj slova/brojeva/praznina/dijakritikih znakova).
Ispiite istu reenicu ali s obratnim poretkom rijei.

36

C++ i osnove objektno orijentiranog dizajna


Uputa: Koristite funkcije. Koristite globalne varijable gdje je potrebno.
3.
Uitajte sa standardnog niz parova oblika string cijeli_broj, pri emu je string niz
znakova bez praznina. String i cijeli broj razdvojeni su jednom prazninom. Oznaka za kraj unosa
je xxx 000. Ispiite broj uitanih parova, srednju vrijednost aritmetikog ekvivalenta stringa
(sume svih znakova), srednju vrijednost numerikog dijela unosa, te srednju vrijednost cijelog
unosa.
Uputa: Koristite funkcije. Koristite globalne varijable gdje je potrebno.
4.
Implementirajte funkcije strlen (duljina stringa), strcpy (kopiranje jednog stringa u
drugi), strcat (dodavanje jednog stringa drugom), strcmp (usporedba dva stringa), int
sum(const char*, const char*) koja vraa zbroj zbroja znakova svakog stringa, te char*
rev(const char*) koja kao povratnu vrijednost vraa ulazni string obrnutog poretka.
Prototipovi funkcija koji nisu navedeni jednaki su onima iz C++.
Uputa: Koristite funkcije. Koristite globalne varijable gdje je potrebno.
5.
Napiite program koji ita ulaznu C++ datoteku te uklanja sve komentare iz nje.
Komentari mogu biti jednolinijski (//), ili blok komentari (/* */). Ime datoteke navodi se u
komandnoj liniji.
Uputa: Koristite funkcije. Koristite globalne varijable gdje je potrebno.
6.
Napiite program koji ita proizvoljan broj ulaznih datoteka, te upisuje njihov sadraj tih
datoteka jedan iza drugog u datoteku koja je zadnja navedena u ulaznoj listi datoteka. Imena
datoteka zadaju se iz komandne linije.
Uputa: Koristite funkcije. Koristite globalne varijable gdje je potrebno.
7.
Napiite program koji ita ulaznu cpp datoteku i zamjenjuje sve pojave naredbe printf
C++ ekvivalentom cout. Novi program pohranjen je u novu datoteku. Imena obje datoteke
navode se iz komandne linije. Ulazni program je pisan tako da se u svakom retku nalazi jedna
naredba.
Uputa: Koristite funkcije. Koristite globalne varijable gdje je potrebno.

37

C++ i osnove objektno orijentiranog dizajna

8 Uvod u OOP
Razvoj programskih jezika i pristupa programiranju pratio je razvoj sloenosti zadataka koji su se
postavljali pred programere:
1. strojni kod,
2. assembler (mainski kod),
3. jezici vieg stupnja (FORTRAN),
4. strukturirano programiranje (PASCAL, C), i
5. objektno orijentirano programiranje (C++).
Svi objektno orijentirani jezici imaju tri zajednike karakteristike:
1. enkapsulacija (klase i objekti),
2. polimorfizam, i
3. nasljeivanje.

38

C++ i osnove objektno orijentiranog dizajna

9 Enkapsulacija
Teme obraene u ovom dijelu:

Objekti i klase
Definicija klasa
Dodjela prava pristupa
Prijateljske funkcije
Umetnute (inline) funkcije
Deklaracija objekta
Kljuna rije this
Konstruktori
Podrazumijevani konstruktor
Konstruktor s parametrima
Konstruktor kopije
Destruktor
Polja objekata
Statiki lanovi
Pokazivai na podatkovne lanove klase
Pokazivai na funkcijske lanove klase
Strukture
Unije

9.1 Objekti i klase


C odvaja podatke (varijable, strukture) od operacija koje se na njima primjenjuju (funkcije).
Objekt je logiki entitet koji ujedinjuje podatke i operacije (metode) nad njima. Povezivanje
podataka i operacija u logiku cjelinu naziva se enkapsulacija.
U C++ kodu objekt predstavlja varijablu korisniki definiranog tipa koji se zove klasa. Objekt je
dakle konkretna realizacija klase koja definira njegovu strukturu. Klase su zapravo strukture iz
programskog jezika C proirene funkcijama.

9.2 Definicija klasa


Prije deklariranje objekta potrebno je definirati klasu, odnosno tip objekta:
class imeKlase{
private:
privatni podaci i funkcije
public:
javni podaci i funkcije
protected:
zatieni podaci i funkcije
} lista_objekata;

Pri definiciji klase postoji mogunost odreivanja prava pristupa pojedinim podacima i
funkcijama unutar klase pomou rijei private, public i protected. Ukoliko se ne navede
nain pristupa smatra se da se radi o private dijelu. Bilo koji pristup moe se ispustiti.

39

C++ i osnove objektno orijentiranog dizajna


Pri definiciji klase nije potrebno uvijek dati definiciju funkcija, njih je mogue definirati i kasnije
uporabom scope resolution operatora:
class imeKlase{
pristup: //ukoliko se pristup ispusti radi se o private
povratni_tip imeFunkcije();
}
povratni_tip imeKlase::imeFunkcije(){} //:: je scope resolution operator

Scope resolution operator odreuje podruje (scope) gdje se funkcija definira, jer se radi o
podruju klase, a ne globalnom podruju na isti nain mogue je pristupiti i bilo kojem podatku
unutar klase, no on se ne smije inicijalizirati jer ne postoji konkretna realizacija te klase (objekt):
class klasa{
int var;
}
klasa::var=1; //greka var ne postoji u memoriji

9.3 Dodjela prava pristupa


Ideja klase je objedinjavanje podataka i operacija nad njima radi lakeg koritenja. public,
private i protected odreuju prava pristupa pojedinim elementima klase preko konkretne
realizacije klase objekta. Korisnik klase ne mora znati implementaciju klase, ve ju koristi
preko definiranog javnog suelja u obliku javnih funkcija i podataka koji se nalaze u public
dijelu definicije. U private i protected dijelu se nalazi dio implementacije koji nije javno
dostupan preko objekta i predstavlja za korisnika nevane implementacijske detalje.
class student{
int ocjena;
public:
void upis(){cin>>ocjena;}
void ispis(){cout<<ocjena<<endl;}
};

Ocjena spada u private dio i moe joj se pristupati samo metodama definiranim unutar klase
(upis() i ispis()) koje predstavljaju javno suelje. Korisnik klase ne mora znati ime varijable u
koju se spremaju ocjene, dovoljno je da zna imena funkcija suelja.

9.4 Prijateljske funkcije


Funkcije koje su lanovi klase mogu pristupati bilo kojem podatku unutar klase bez obzira na tip
pristupa, funkcije izvan klase (free functions) mogu pristupati samo javnim podacima.
Prijateljske funkcije su funkcije definirane izvan klase koje mogu pristupati svim podacima klase:
class klasa{
int privateVar;
public:
friend int prijatelj(klasa); //prijatelj(klasa) je prijateljska funkcija
klasi klasa
};
int prijatelj(klasa obj){
return obj.privateVar; //pristup privatnoj varijabli klase
}

9.5 Umetnute (inline) funkcije


Tijela kratkih funkcija je efikasnije umetnuti pri prevoenju umjesto poziva funkcije. Kljunom
rijei inline daje se uputa prevodiocu da poziv zamjeni tijelom funkcije i ima smisla za kratke

40

C++ i osnove objektno orijentiranog dizajna


funkcije koje se esto pozivaju. Svaka funkcija koja je definirana unutar klase automatski se
smatra umetnutom, te nije potrebno navoditi rije inline:
class klasa{
int var;
public:
int getVar(void){return var;} //getVar je inline funkcija
inline float f(void);
};

Umetnutu funkciju je mogue definirati i izvan klase, ali je tada potrebno navesti rije inline:
klasa::inline float f(void){}

9.6 Deklaracija objekta


Objekt se deklarira kao bilo koja druga varijabla u programu:
class klasa{
int a;
public:
int b;
int f(void){return a};
};
void main(void){
klasa objekt;
klasa *pokObjekt=new klasa;
}

lanovima klase pristupa se pomou operatora pristupa:


1. operator . ako se na objekt referira pomou naziva objekta ili reference:
objekt.b=1;
int c=objekt.f();
objekt.a=1; //greka a je varijabla s private pristupom

2. operator -> ako se na objekt referira pomou pokazivaa:


pokObjekt->b=2;
int d=pokObjekt->f();

9.7 Kljuna rije this


Prilikom poziva svakog funkcijskog lana kao skriveni parametar se prenosi pokaziva na objekt
kojem taj lan pripada:
class klasa{
int a;
public:
int f(int b){a=a*b;}
};
void main(void){
klasa obj;
obj.f(2);
}

Kljuna rije this najee se koristi kada treba vratiti pokaziva ili referencu na objekt koji je
pozvan.
class klasa{
int a;
public:
int f(int b, klasa *this) {(this->a)=(this->a)*b;}
};

41

C++ i osnove objektno orijentiranog dizajna


void main(void){
klasa obj;
obj.f(2,&obj);
}

9.8 Konstruktori
Konstruktor je dio koda koji izvodi inicijalizaciju podataka prilikom deklaracije objekta
konstruktor je funkcija ije je ime jednako imenu klase i koja nema povratne vrijednosti jer samo
obavlja operacije:
class klasa{
int a,b,c;
public:
klasa(void); //konstruktor
};
klasa::klasa(void):a(1),b(2){ //definicija konstruktora
cout<<Konstruktor poceo<<endl;
c=a+b;
cout<<Konstruktor zavrsio<<endl;
}

Prije navoenja tijela konstruktora mogue je navesti inicijalizacijsku listu u obliku:


imeKlase::imeKlase():var1(vrijednost1),var2(vrijednost2){}

Konstruktor se automatski poziva pri deklaraciji objekta:


klasa objekt;
cout<<objekt.a<<endl; //1

9.8.1 Podrazumjevani konstruktor


Konstruktor bez parametara se naziva podrazumjevani konstruktor (default constructor). Ako
klasa nema konstruktora prevoditelj automatski stvara podrazumjevani konstruktor koji poziva
podrazumijevane konstruktore klasa iji se objekti nalaze unutar promatrane, a njezine
podatkovne lanove ostavlja neinicijalizirane:
class klasa{
int a, b;
public:
klasa(void){a=1; b=2;};
};
class klasaBezKonstruktora{
klasa c;
int d, e;
};
void main(void){
klasaBezKonstruktora f; //poziva se podrazumjevani konstruktor
klasa::klasa(void), dok varijable d i e ostaju neinicijalizirane
}

9.8.2 Konstruktor s parametrima


Pri deklaraciji objekta mogue je konstruktoru prenijeti i neke inicijalizacijske parametre:
class klasa{
char *polje;
public:
klasa(int velicina){
polje=new char[velicina+1];
}
};

42

C++ i osnove objektno orijentiranog dizajna


Vrijednost tih parametara potrebno je navesti pri deklaraciji objekta (u protivnom e se pozvati
podrazumjevani konstruktor ili e se takav stvoriti ako ne postoji):
klasa objekt(20);

9.8.3 Konstruktor kopije


Konstruktor kopije opisuje nain inicijalizacije lanova objekta kojem se pridruuje drugi objekt:
klasa obj1();
klasa obj2=obj1; //pozivanje konstruktora kopije

Razlikuje se od drugih konstruktora po tome to ima kao argument referencu na konstantan


objekt iste klase:
imeKlase::imeKlase(const imeKlase &ref){}

Ukoliko se konstruktor kopije ne definira prevoditelj e ga sam generirati pri emu se elementi
jednog objekta inicijaliziraju vrijednostima elemenata drugog objekta. To moe predstavljati
problem kod dinamikih objekata:
class klasa{
char *polje;
public:
klasa(int d);
klasa(const klasa &refKlasa)
};
klasa::klasa(int d):polje(new char[d]){}
klasa::klasa(const klasa &refKlasa):polje(new char[sizeof(refKlasa.polje)]){
for(int i=0;i<sizeof(refKlasa.polje);i++)
polje[i]=refKlasa.polje[i];
}

9.8.4 Destruktor
Destruktor se poziva prilikom unitavanja (uklanjanja) objekta iz memorije ima naziv jednak
imenu klase ispred kojeg stoji ~ (tilda). Destruktor ne moe imati parametre.
Automatski se poziva kod

automatskih objekata na kraju bloka u kojem su definirani


statikih i globalnih objekata nakon izlaska iz funkcije main()
dinamikih objekata prilikom unitenja sa delete

Destruktor se ne mora definirati za statike objekte koji ne zauzimaju nikakve dodatne resurse:
class obj{
public:
int a;
};
klasa obj; //ne treba destruktor jer se automatski unitava pri izlasku iz
bloka

Dinamike objekte potrebno je eksplicitno unititi sa delete


klasa *pokObj=new klasa;

delete pokObj; //ne treba imati definiran destruktor jer se ne alocira nikakva
dinamika struktura unutar klase

Ako se unutar klase dinamiki rezervira memorijski prostor potrebno ga je eksplicitno osloboditi
unutar destruktora jer takvi objekti ne spadaju u automatske:
43

C++ i osnove objektno orijentiranog dizajna


class klasa{
int *polje;
public:
klasa(int d):polje(new int[d]); //dinamika alokacija polja
~klasa(void); //deklaracija destruktora
};
klasa::klasa(void){delete [] polje}; //destruktor unitava dinamiki alocirano
polje u konstruktoru

Poziv destruktora moe biti automatski (izlazak iz bloka) ili eksplicitan (delete) to ovisi o
deklaraciji objekta.

9.9 Polja objekata


Mogue je definirati polja objekata slino kao i polja ugraenih tipova:
klasa poljeObjekata[duljina_polja];

Prilikom deklaracije polja poziva se podrazumjevani konstruktor ili konstruktor s parametrima


ako je navedena inicijalizacijska lista:
klasa polje[2]={klasa(), klasa()}

Kod dinamike alokacije polja mora postojati podrazumjevani konstruktor, jer tu nema
mogunosti navoenja inicijalizacijske liste:
klasa *polje=new klasa[5];

Pri oslobaanju polja potrebno je pozvati destruktore za sve lanove polja:


delete polje; //poziva se destruktor prvog lana loe rjeenje
delete [] polje; //pozivaju se destruktori svih lanova polja

Pomou delete [] mogu se osloboditi samo lanovi alocirani operatorom new.

9.10 Statiki lanovi


Statiki su lanovi zajedniki svim objektima jedne klase (globalni su za cijelu klasu) i slini su
globalnim lanovima samo to su vidljivi iskljuivo u podruju klase:
class klasa{
static int staticki; //deklaracija statike varijable
static int f(void); //deklaracija statike funkcije
};

Deklaracija statikog lana slui samo kao najava programu da e u memoriji postojati lan
zajedniki za sve objekte te klase. Stvarno zauzee memorije odvija se pri inicijalizaciji lana.
Statiki lanovi mogu se dohvatiti bez objekta pomou imena klase i scope resolution
operatora:
klasa::staticki=0; //inicijalizacija statikog lana

Statikim funkcijama se pristupa slino kao i statikim podatkovnim lanovima:


imeKlase::imeFunkcije

Statikim lanovima mogue je pristupiti i preko objekata:


klasa objekt;
objekt.staticki=0;

9.11 Pokazivai na podatkovne lanove klase


Mogue je deklarirati pokaziva na lan klase kao:

44

C++ i osnove objektno orijentiranog dizajna


tiplana imeKlase::*imePokazivaa;

Pokazivai na lan klase razlikuju se od obinih pokazivaa jer ne pokazuju na neku konkretnu
memorijsku lokaciju, ve samo jednoznano identificiraju lan klase:
class klasa{
public:
int a;
};
void main(void){
int klasa::*pok1=&klasa::a; //pok1 je pokaziva na lan klase
klasa obj;
int *pok2=&obj.a; //pok2 je pokaziva na memorijsku lokaciju
obj.a=1;
cout<<obj.a<<endl;
cout<<obj.*pok1<<endl; //pok1 je drugo ime za lan a
}

9.12 Pokazivai na funkcijske lanove klase


Osim pokazivaa na podatkovne lanove mogue je definirati i pokaziva na funkcijske lanove
klase:
povratni_tip (imeKlase::imePokazivaa)(tip1, tip2, )

Pri pridjeljivanju vrijednosti pokazivau nije potrebno naglasiti da se uzima adresa:


class klasa{
public:
int f(int, double);
};

void main(void){
klasa *obj=new klasa;
int (klasa::pokF)(int, double)=klasa::f;
cout<<obj->pokF(1,1.2);
}

Prilikom pridruivanja vrijednosti pokazivau provjerava se potpis i pripadnost funkcije


potrebno je podudaranje povratnog tipa, argumenata i klase funkcijskog pokazivaa i pridjeljene
funkcije.

9.13 Strukture
U C++ struktura ima ista svojstva kao i klasa moe sadravati podatkovne i funkcijske lanove.
Razlika je u tome to je kod klase podrazumjevani pristup privatni (private), a kod strukture
javni (public):
struct struktura{
int velicina;
void pisi(int nova){velicina=nova;};
int citaj(void){return velicina};
};
void main(void){
struktura objekt; //nije potrebno navoditi struct kao u C-u
objekt.pisi(2);
int b=objekt.citaj();
}

9.14 Unije

45

C++ i osnove objektno orijentiranog dizajna


Sline su strukturama i klasama samo to podaci dijele isti memorijski prostor. Veliina unije
jednaka je veliini najveeg podatkovnog lana. Deklaracija ista deklaraciji klase (mogunost
navoenja pravila pristupa, funkcijske lanove, podatke, ):
union Unija{
long kapacitet;
int brojStr;
};
void main(void){
Unija objekt; //nije potrebno navoditi union kao u C-u
Unija.kapacitet=12345;
cout<<Unija.brojStr; //ispis e ovisiti o nainu pohranjivanja u
memoriji
}

Unije se koriste za ouvanje memorijskog prostora ukoliko je potrebno koristiti vie atributa
razliitog tipa, ali pri emu samo jedan atribut u nekom trenutku ima neko znaenje.
Unija moe sadravati objekte klasa pod uvjetom da oni nemaju definiran ni konstruktor ni
destruktor. Unija moe sadravati vie konstruktora i destruktor, ali ne moe sadravati statike
lanove. Ukoliko se prvo pristupa ne navede podrazumijeva se javni (public) pristup.
Za odreivanje koji je lan unije aktivan esto se koristi podatkovni lan koji se naziva
diskriminantom unije:
class Klasa{
enum { kapacitet, stranice} tip; //tip je diskriminanta unije
union{
long kapacitet;
int brojStr;
} objektUnije;
public:
void ispis(void);
};
Klasa::ispis(void){
if(tip==kapacitet) cout<<objektUnije.kapacitet<<endl;
else cout<<objektUnije.brojStr<<endl;
};

Mogue koritenje anonimne unije kojoj nije dodijeljeno ime za izravan pristup lanovima - unije
koje nemaju niti naziv unije niti naziv varijable koja se deklarira:
class Klasa{
enum { kapacitet, stranice} tip; //tip je diskriminanta unije
union{ //anonimna unija
long kapacitet;
int brojStr;
};
public:
void ispis(void);
};
Klasa::ispis(void){
if(tip==kapacitet) cout<<kapacitet<<endl;
else cout<<brojStr<<endl;
};

9.15 Primjeri zadataka


1.

Implementirajte jednostruko povezanu listu cijelih brojeva.

46

C++ i osnove objektno orijentiranog dizajna


Metode: dodavanje elementa na poetak/kraj/iza nekog elementa, brisanje zadanog elementa,
ispis liste
Naputak: koristite klasu koja implementira atomarni element liste (vrijednost, pokaziva na
sljedei lan)
2.

Implementirajte dvostruko povezanu sortiranu listu cijelih brojeva.

Metode: dodavanje elementa, brisanje zadanog elementa, ispis liste, kretanje kroz listu
(prethodni, sljedei element)
Naputak: koristite klasu koja implementira atomarni element liste (vrijednost, pokaziva na
sljedei i prethodni lan)
3.

Implementirajte rep cijelih brojeva organiziran po LIFO principu.

Metode: dolazak elementa, odlazak elementa, ispis repa, kretanje kroz rep (prethodni, sljedei
element)
Naputak: koristite klasu koja implementira atomarni element repa (vrijednost, potrebni
pokazivai)
4.

Implementirajte stog cijelih brojeva.

Metode: stavljanje elementa (push), skidanje elementa (pop), ispis stoga, kretanje kroz stog
(prethodni, sljedei element)
Naputak: koristite klasu koja implementira atomarni element stoga (vrijednost, potrebni
pokazivai)
5.
Implementirajte niz cijelih brojeva kojem se dinamiki mijenjaju dimenzije (npr. korisnik
moe pristupiti bilo kojem lanu bez deklaracije duine polju se automatski poveava duina da
moe realizirati zahtjev). Zadatak rijeiti uz minimalan broj dealokacija (slijedna struktura)
Metode: pristup lanu (getAt(int)), upisivanje vrijednosti lana (putAt(int))
Naputak: Koristite implementaciju pomou liste. Koristite klasu koja implementira atomarni
element liste (vrijednost, potrebni pokazivai).
6.
Implementirajte spremnik sustava posluivanja s prioritetima. Ukupno postoji 5 prioriteta
paketa (1 do 5), pri emu je 1 najmanji prioritet paketa. Svaki prioritet ima svoj red ekanja.
Svaki paket ima svoj prioritet i jedinstveni ID.
Metode: dolazak novog paketa, odlazak paketa, ispis reda svakog prioriteta, ispis broja paket a u
redu svakog prioriteta.
Naputak: Koristite implementaciju pomou liste. Koristite klasu koja implementira atomarni
element liste (vrijednost, potrebni pokazivai).

47

C++ i osnove objektno orijentiranog dizajna

7.
Implementirajte spremnik WDM multipleksera iz kojeg izlazi 16 kanala (valnih duljina).
Svaki paket ima svoj jedinstveni identifikacijski broj kao i cjelobrojnu oznaku kanala kojem
pripada (1-16). Za svaki kanal se stvara poseban red ekanja organiziran po FIFO naelu.
Metode: dolazak novog paketa, odlazak paketa, ispis reda ekanja svakog kanala, ispis broja
paketa u redu ekanja svakog kanala.
Naputak: Koristite implementaciju pomou liste. Koristite klasu koja implementira atomarni
element liste (vrijednost, potrebni pokazivai).

48

C++ i osnove objektno orijentiranog dizajna

10 Polimorfizam
Teme obraene u ovom dijelu:

to je polimorfizam
Preoptereenje funkcija
Korisniki definirane konverzije
Konverzija konstruktorom
Operator konverzije
Preoptereenje operatora
Definicija operatorske funkcije
Operator =
Operator []
Operator ()
Operator ->
Prefiks i postfiks operatori ++ i
Operator umetanja <<

10.1 to je polimorfizam
Jedno se ime koristi za vie razliitih ali meusobno srodnih operacija, tj. za definiranje skupa
srodnih operacija. Ovisno o prenesenim parametrima ili ulaznom tipu poziva se specifina
realizacija, no korisnik mora znati samo jedinstveno ime i tipove podataka koji se s njime mogu
koristiti.
Mehanizam polimorfizma ini

preoptereenje funkcija (function overloading), i

preoptereenje operatora (operator overloading).

10.2 Preoptereenje funkcija


Jedno ime dijeli vie funkcija koje obavljaju slinu ili istu operaciju nad razliitim tipom
podataka:
int umanjiZaJedan(int);
float umanjiZaJedan(float);

Koja e se implementacija funkcije pozvati ovisi o prenesenom parametru:


float a=umanjiZaJedan(5.2); //poziv funkcije float manjiZaJedan(float);

Vrlo esto se preoptereuju i konstruktori, tako da se uz podrazumjevani navede i konstruktor s


parametrima:
class vrijeme{
int t;
public:
vrijeme(void):t(0);
vrijeme(int offset):t(offset);
};
void main(void){
vrijeme obj1; //poziv podrazumijevanog konstruktora

49

C++ i osnove objektno orijentiranog dizajna

vrijeme obj2(5); //poziv konstruktora s parametrom

10.3 Korisniki definirane konverzije


Ugraene konverzije su konverzije izmeu nekih ugraenih parametara (unsigned int->int,
float->double). Korisnik moe definirati konverziju izmeu ugraenih i
korisnikih tipova u oba smjera, pri emu proiruje skup moguih konverzija na korisniki
definirane tipove.

int->float,

Primjer korisniki definirane konverzije je konverzija char pokazivaa u objekt klase string
koji sadri polje znakova i operacije nad njima, te obratno pretvorbu objekta klase string u char
pokaziva na prvi lan polja znakova.
Struktura klase string:
class string{
char *znNiz;
public:
string(char *niz=);
string(const string &ref);
~string(void);
char *pok(void) {return znNiz};
};

10.3.1 Konverzija konstruktorom


Konstruktor s jednim parametrom moe se upotrijebiti za konverziju podatka tipa parametra
konstruktora u objekt klase:
string::string(char *niz=):znNiz(new char[strlen(niz)+1]){
strcpy(znNiz,niz);
}
string::string(const string &ref):znNiz(new char[strlen(ref.znNiz)+1]){
//konstruktor kopije
strcpy(znNiz, ref.znNiz);
}
string::~string(void){delete [] znNiz;}

Konverzije konstruktorom se koriste pri inicijalizaciji objekta ili prijenosu podatka u funkciju:
void f(znNiz){}
void main(void){
string obj=C++; //konverzija pri inicijalizaciji - isto kao i string
obj(C++);
f(TKI); //konverzija prilikom prijenosa parametra

Prilikom ulaska u funkciju stvara se privremeni objekt pomou konstruktora s jednim


parametrom, pri emu on odgovara stvarnom parametru prenesenom u funkciju.
10.3.2 Operator konverzije
Operatorom konverzije definiraju se pravila pretvorbe podatka u neki drugi tip, pri emu se
konverzija obavlja pomou posebnog funkcijskog lana:
operator tip(); //tip se zamjenjuje nazivom tipa u kojeg se obavlja pretvorba

Operator konverzije nema povratni tip i parametre. U klasi string mogue je definirati operator
konverzije koji vraa pokaziva na prvi lan znakovnog niza ili vraa duljinu znakovnog niza:
class string{

50

C++ i osnove objektno orijentiranog dizajna


public:
operator char*(){//operator konverzije koju
return znNiz; //vraa pokaziva na prvi lan znakovnog niza
}
operator int(){
return strlen(znNiz);
}
};

Pri pozivu funkcije prvo se trai ugraena konverzija, a zatim korisniki definirana konverzija u
odgovarajui tip ili tip na kojem postoji ugraena konverzija u odgovarajui tip:
void
void
void
void

f1(int a);
f2(long a);
f3(char *a);
main(void){
string obj(C++);
f1(obj); //string->int
f2(obj); //string->int->long prvo korisnika pa ugraena konverzija
f3(obj); //string->char*

Nisu mogue dvije uzastopne korisnike konverzije (samo korisnika pa ugraena). Mogue je i
direktno navesti tip u koji se obavlja konverzija:
void f(int a);
void f(char *a);
void main(void){
string obj(C++);
f((int) obj); // ili f(int(obj));
}

10.4 Preoptereenje operatora


U C++ jeziku se ne mogu preopteretiti svi operatori:

operatori koji se ne mogu preopteretiti, i

operatori koji se mogu preopteretiti.

Nije mogue uvesti novi operator. Svaki operator zadrava broj argumenata po standardnoj C++
sintaksi. Neki operatori (+ - & *) mogu se preopteretiti u obje (unarnoj i binarnoj) inaici.
Operatore je mogue preopteretiti za korisnike tipove, ali ne i za ugraene tipove
sizeof
delete
*=
||
>=
|

?:
new
|=
&&
<=
&

::
->*
&=
!=
>
^

.*
->
^=
==
<
%

.
()
%=
>>
=
/

[]
/=
<<
,
*

>>=
-=
-!
-

<<=
+=
++
+

10.4.1 Definicija operatorske funkcije


Izraz c=a+b; prevodi se kao poziv operatorske funkcije s dva argumenta:
c=operator+(a,b);

Preoptereenje operatorske funkcije se obavlja koritenjem dueg oblika poziva operatorske


funkcije:
class kompl{
friend kompl operator+(kompl &a, kompl &b);
int re, im;

51

C++ i osnove objektno orijentiranog dizajna


public:
kompl(int a=0, int b=0):re(a),im(b);
};
kompl operator+(kompl &a, kompl &b){
return kompl(a.re+b.re, a.im+b.im);
}

Operacija zbrajanja je deklarirana kao prijateljska funkcija da bi se mogla pozivati u globalnom


podruju bez operatora razluivanja podruja i da bi mogla pristupati podacima unutar klase:
kompl a(1,2), b(3,4), c;
c=a+b; //c.re=1+3, c.im=2+4

Operatorska funkcija moe biti definirana kao lan klase ili samostalna funkcija. Operatorska
funkcija definirana unutar klase ima za jedan manje parametar od operatorske funkcije definirane
izvan klase koja obavlja operaciju nad istim brojem podataka:
class klasa{
public:
klasa operator-(const klasa &desni);
};
klasa operator+(const klasa &lijevi, const klasa &desni);

klasa obj1, obj2;


obj1-obj2; //interpretira se kao obj1.operator-(obj2)
obj1+obj2; //interpretira se kao operator-(obj1, obj2)

Za operatorske funkcije definirane izvan klase svi operandi se prosljeuju kao argumenti
operatorske funkcije. Za operatorske funkcije definirane unutar klase poziva se funkcijski lan
objekta lijevo od operatora kojem se prosljeuje lan desno od operatora. Kad je operator
definiran kao funkcijski lan na lijevi operand se ne primjenjuju korisnike konverzije.
Klasu kompl moemo proiriti operatorom kao funkcijskim lanom:
class kompl{

public:
kompl operator-(const kompl &b){
return kompl(re-b.re, im-b.im);
};

kompl a,b,c;
c=a+b;
c=a-b;
c=1+b; //na 1 se obavlja korisnika konverzija konstruktorom
c=1-b; //na 1 se ne obavlja konverzija : 1.operator-(b) nema smisla

Nije mogue definirati binarni operator koji kao argument nema ni jedan objekt klase jer bi se
time promijenilo znaenje ugraenog operatora.
10.4.2 Operator =
Operatori = i & automatski su definirani za svaku klasu. Operator = potrebno je definirati unutar
klase, ako se eli izbjei generiranje podrazumijevanog operatora pridruivanja koji pridruuje
vrijednosti istovrsnih elemenata jednog objekta drugom.
Podrazumjevani operator pridruivanja nije dobar u svim sluajevima:
class string{

public string& operator=(const string &desno);


};
string& string::operator=(const string &desno){

52

C++ i osnove objektno orijentiranog dizajna


if(&desno!=this){
delete [] znNiz;
znNiz=new char(strlen(desno.znNiz)+1) <
}
return *this;
}

Istu funkciju obavljao je i konstruktor kopije klase string. Pri ovakvoj definiciji operatora
pridruivanja mogue je obaviti ulanavanje jer je povratni tip referenca:
obj a,b;
a=b=C++; //C++ se pridjeljuje objektu b, a objekt b objektu a

10.4.3 Operator [] []
Operator [] (operator indeksiranja) koristi se za dohvat lanova polja.
Poziv obj[ind] interpretira se kao
obj.operator[](ind);

klasu string nadopunjujemo operatorom indeksiranja koji e vratiti lan polja znNiz:
class string{

public:
char& operator[](int poz){return znNiz[n]}
};

string obj(C++);
cout<<obj[1]<<endl; //+

10.4.4 Operator () ()
Operator za poziv funkcije () moe imati proizvoljan broj argumenata.
Poziv obj(arg) se interpretira kao
obj.operator()(arg);

U klasi string moemo preopteretiti operator () tako da vraa podniz odreen pozicijom prvog
lana i duljinom podniza:
class string{

public:
string operator()(int, int);
};
string string::operator()(int start, duljina){
char pom[100], *pok1=pom, *pok2=znNiz+start;
while(duljina-- && *pok2) *(pok1++)=*(pok2++);
return string(pom);
}

10.4.5 Operator ->


-> se uvijek preoptereuje kao unarni i mora biti definiran kao funkcijski lan. Izraz a->b

interpretira se kao
1. pristup lanu b ako je a pokaziva na objekt neke klase, ili
2. ako je a obini objekt ili referenca poziva se (a.operator->())->b.
class A{
public:

53

C++ i osnove objektno orijentiranog dizajna


int clan;
A(int init):clan(init);
};
class B{
A &refA;
B(A &ref) : refA(ref);
A *operator ->() {return &refA;}
};
class C{
B &refB;
C(B &ref) : refB(ref);
B &operator ->() {return refB;}
};
void main(void){
A objA(1); B objB(objA); C objC(objB);
cout<<objC->clan<<endl; //1. objC->clan => 2. objB->clan =>
objA->clan =>1

10.4.6 Prefiks i postfiks operatori ++ i -Prefiks i postfiks oblik operatora ++ i - razlikuju se u potpisu:
prefix verzija
postfix verzija

unutar klase

izvan klase

void
void
void
void

void
void
void
void

operator++()
operator--()
operator++ (klasa &obj)
operator-- (klasa &obj)

operator++(int)
operator--(int)
operator++ (klasa &obj, int)
operator-- (klasa &obj, int)

Prilikom poziva postfiks verzije int parametar ima neku podrazumijevanu vrijednost koju
odreuje prevoditelj, ili je mogue tu vrijednost eksplicitno navesti:
obj.operator++(15);

10.4.7 Operator umetanja <<


Operator umetanja (insertion operator) koji se koristi pri ispisu je obini bitovni posmak u
lijevo (varijabla << broj mjesta) koji je preoptereen tako da s lijeve strane prihvaa
referencu na objekt klase ostream, a s desne strane bilo koji ugraeni tip (preoptereenje za sve
ugraene tipove):
ostream& operator<< (ostream&, const tip&);

Na izlaz se ispisuje objekt tipa tip. Preoptereenje je mogue napraviti za bilo koji izvedeni tip,
pri emu se obino operatorska funkcija navodi kao prijateljska:
class klasa{
protected:
int a;
public:
friend ostream& operator<< (ostream&, const klasa&);
};
ostream& operator<< (ostream& os, const klasa& obj){
os<<obj.a;
return os;
};

Potrebno je vratiti referencu na izlazni tok os ako se eli omoguiti ulanavanje. Inae bi pri
svakom pozivu operatorske funkcije dolo do stvaranja kopije objekta:
klasa obj1, obj2;
cout<<obj1<<obj2<<endl; //operatorska funkcija se poziva dva puta

10.5 Primjeri zadataka


Implementirajte kvadratnu matricu realnih brojeva proizvoljnih dimenzija.
54

C++ i osnove objektno orijentiranog dizajna


Metode: preoptereenje operatorskih funkcija:
konstruktor
kopije
Matrica(double
**
,int
brRedaka,int
brStupaca)
(x,y) dohvat elementa na odreenoj poziciji (npr. m(1,2) dohvaa element u 1 retku i 2 stupcu)
[x] ispis cijelog retka x
= pridruzivanje matrice
+ zbrajanje matrica
- oduzimanje matrica
| transponiranje matrice
* mnoenje matrica
<< ispis matrice na standardni izlaz

Naputak: matricu implementirajte kao 2 dim polje .


2.

Implementirajte vektor realnih brojeva proizvoljne dimenzije (duljine).

Metode: preoptereenje operatorskih funkcija:


konstruktor kopije Vektor(double *,int duljina)
[x] dohvat komponente vektora na poziciji x
= pridruzivanje vektora
* skalarno mnoenje vektora
| vektorski umnoak vektora (samo dimenzije 3)
+ zbrajanje vektora
- (binarni)oduzimanje vektora
- (unarni)vektor suprotnog smjera
<< ispis vektora na standardni izlaz

Naputak: vektor implementirajte kao 1 dim polje.Zadani operatori trebaju raditi i u kombinaciji
sa konstantama(pretvorba u vektor odgovarajue dimenzije)
3.

Implementirajte prikaz kompleksnih brojeva. Realni i imaginarni dio su realni brojevi.

Metode: preoptereenje operatorskih funkcija:


= prdruzivanje kompleksnog broja, realne konstante
+

zbrajanje kompleksnih brojeva

- (binarni)oduzimanje kompleksnih brojeva


- (unarni)negativan kompleksni broj
* mnoenje kompleksnih brojeva

55

C++ i osnove objektno orijentiranog dizajna


/

dijeljenje kompleksnih brojeva

<< ispis kompleksnog broja u obliku Re+j*Im na standardni izlaz

Naputak: Za implementaciju prikaza kompleksnih brojeva koristite klase. Zadani operatori


moraju raditi i u kombinaciji sa konstantama.
4.

Implementirajte polje za prikaz brojeva u heksadekadskom sustavu.

Metode: preoptereenje operatorskih funkcija:


= pridruzivanje polja, heksadekadskog broja
[] dohvat znamenke na zadanoj poziciji (indeksiranje kao u poljima)
+ zbrajanje brojeva
- (binarni) oduzimanje brojeva
- (unarni) negativan broj
* mnoenje brojeva
<< ispis broja na standardni izlaz

Naputak: Za implementaciju prikaza brojeva koristite klase. Rijeite zadatak primjenom polja
znakova (char) zbog prikaza znamenaka 10-15 (A-F).
5.

Implementirajte prikaz stringa (niza znakova).

Metode: preoptereenje operatorskih funkcija:


= pridruzivanje objekta, konstantnog znakovnog niza(const char *)
[] dohvat znaka na zadanoj poziciji (indeksiranje kao u poljima)
+ konkatenacija (spajanje) stringova (ana+na+as=ananas)
- presjek stringova (ostaju samo zajedniki znakovi ZAGREB-FER=RE)
* shuffle dva stringa (C++ * FER=CF+E+R)
<< ispis stringa na standardni izlaz

Naputak: Za implementaciju prikaza stringa koristite klase. Implementaciju provedite


koritenjem niza znakova (char). Operatorske funkcije moraju raditi i u kombinaciji konstante
(znaka ('.') ili stringa ("...")) i objekta u bilo kojem poretku.
6.

Implementirajte jednostruko povezanu nesortiranu listu cijelih brojeva.

Metode: preoptereenje operatorskih funkcija:


konstruktor Lista(int * polje,int duljina)
= pridruzivanje objekta
[] element na zadanoj poziciji (indeksiranje kao u poljima)

56

C++ i osnove objektno orijentiranog dizajna


+ konkatenacija (spajanje) dvije liste (A+B=AB)
- presjek lista (ostaju samo zajedniki elementi, npr. A->B->C->D->E R->E->F->A=A->E)
<< ispis liste

Naputak: Za implementaciju prikaza liste koristite klase.


7.

Implementirajte prikaz kompleksnih brojeva u trigonometrijskom obliku

Metode: preoptereenje operatorskih funkcija:


= pridruzivanje objekta, realne konstante
+ zbrajanje kompleksnih brojeva
- (binarni) oduzimanje kompleksnih brojeva
- (unarni) negativan kompleksni broj
* mnoenje kompleksnih brojeva
/

dijeljenje kompleksnih brojeva

<< ispis kompleksnog broja u obliku (|Z| | kut) na standardni izlaz

Naputak: Za implementaciju prikaza kompleksnih brojeva koristite klase. Zadani operatori


moraju raditi i u kombinaciji sa konstantama.

57

C++ i osnove objektno orijentiranog dizajna

11 Nasljeivanje
Teme obraene u ovom dijelu:

to je nasljeivanje
Zadatak
Sveoptika mrea s WDM
Optike komponente
Prijenos znanja u C++
Odnosi meu komponentama (taksonomija)
Bazna klasa
Specificiranje nasljeivanja
Nasljeivanje i prava pristupa
Nasljeivanje i relacije
Viestruko nasljeivanje
Virtualna osnovna klasa
Karakteristike virtualnog nasljeivanja
Pristup lanovima izvedenih klasa
Ugraene pretvorbe i nasljeivanje
Konstruktori i destruktori izvedenih klasa
Podruje pretraivanja
Ugnijeeni tipovi
Klase kao argumenti funkcija (ugraene konverzije)
Klase kao argumenti funkcija (korisnike konverzije)
Nasljeivanje i preoptereeni operatori
Polimorfizam i tipovi vezivanja
Pozivi virtualnih funkcijskih lanova (nastavak)
iste virtualne funkcije
Virtualni destruktori
Polimorfizam i proirivost koda

11.1 to je nasljeivanje?
Svaki objektno orijentirani jezik mora imati implementiran mehanizam nasljeivanja. U dobrom
definiranju pojma i mehanizama nasljeivanja lei temelj razumijevanja ideje objektno
orijentiranog programiranja. Zbog kompleksnosti i apstraktnosti koju uvodi sustav nasljeivanja,
u njegov opis kreemo postavljanjem konkretnog problema u kojem e biti vidljivi i neki koraci
objektno orijentiranog dizajna (OOD).

11.2 Zadatak
Zadatak

Simulator sveoptike mree s valnim multipleksom.


Rjeenje

58

C++ i osnove objektno orijentiranog dizajna


Oito je da rjeenje ovog problema nee biti izloeno u cjelini zbog ekstenzivnosti I
nedefiniranosti problema. No neki temeljni koraci se ipak mogu provesti bez obzira na openitost
zadatka.
Tekstu zadatka treba pristupiti analitiki, tj. probati (korektno) izvui to vie informacija. Pri
tome imamo dva kljuna pojma:
1. simulator potrebno je modelirati pojave s nekim ulaznim veliinama u svrhu analize
njihovog izlaza, i
2. sveoptika mrea s valnim multipleksom predmet simulacije e biti sveoptika mrea s
valnim multipleksom (WDM).
Jasno je da iako imamo neku intuitivnu i iskustvenu sliku o simulatoru nije mogue krenuti u
njegovo projektiranje bez detaljnije specifikacije zahtjeva na njegove funkcije. No neke kljune
stvari vezane uz simulatore e sigurno biti potrebne i u ovom sluaju. Svaka mrea, pa tako i
sveoptika s WDM se sastoji od vorova i linkova. U vorovima se nalaze neki fiziki ureaji, a
linkove u ovom sluaju ine optiki vodovi. Mogli bi dakle specificirati tipove podataka koji e
sadravati parametre fizikih elemenata koji e sainjavati mreu, kao i metode kojima emo se
sluiti pri njihovoj uporabi.
11.2.2 Sveoptika mrea s WDM
Oito je da drugi korak ne moemo uiniti bez znanja o sveoptikoj mrei s WDM, tj. o optikim
komponentama koje bi eljeli opisati. Probajmo prvo definirati sveoptiku mreu:
Sve-optika mrea je telekomunikacijska transportna mrea u kojoj se prijenos informacije izvodi
potpuno u optikoj domeni. Signal koji prenosi informaciju je elektrini samo u pristupnim
tokama takove mree, tj. optikim prijemnicima i predajnicima.
Zatim odredimo to je to sveoptika mrea s valnim multipleksom:
Specijalan sluaj sve-optike mree je mrea s valnim multipleksom (engl. Wavelength Division
Multiplex, WDM, ili Dense WDM, DWDM). U takvoj se mrei potencijalno ogroman kapacitet
vlakna iskoritava frekvencijskim multipleksom, tj. vie se signala s informacijama kroz vlakno
prenosi na razliitim frekvencijama. S obzirom da se u optici umjesto frekvencije ee koristi
pojam valne duljine, taj je nain optikog prijenosa nazvana valnim multipleksom, izmeu
ostalog i da se naglasi optiki karakter multipleksa.
Pojam sveoptike mree sada je jasniji, no jo uvijek ostaju nedefinirani elementi takve mree
iako nasluujemo da se radi o prijamnicima, predajnicima, multiplekserima, optikim vlaknima
11.2.3 Optike komponente
Probajmo sada popisati komponente uz kratak opis njihove funkcije koji e biti nuan za
definiranje atributa tih komponenata:

predajnik. Pretvara signal iz elektrine domene u optiku. Postoji mnotvo vrsta optikih
predajnika, no u sve-optikim mreama se koriste iskljuivo laserski predajnici i to veim
udjelom poluvodiki, odnosno u manjoj mjeri plinski. Dakle, radi se o komponenti koja
ima jedan elektriki ulaz, te jedan optiki izlaz.

59

C++ i osnove objektno orijentiranog dizajna

prijemnik. Pretvara optiki signal u elektrini. Kao i u sluaju predajnika, moemo rei da
se radi o tzv. opto-elektrinoj komponenti. Sadri jedan optiki ulaz, te jedan elektriki
izlaz.

transponder. U dananjim sve-optikim mreama s valnim multipleksom se iskljuivo


koristi 3. optiki prozor za prijenos informacija (valne duljine oko 1500nm), no esto je
signal koji ulazi u sve-optiku mreu ve u optikom obliku, no nepogodan za direktan
prijenos preko sve-optike mree. Primjerice, moe se raditi o optikom signalu na valnoj
duljini od 1300nm (2. optiki prozor). S druge pak strane, problem moe leati I u
formatu (primjerice linijskom kodu) takvog optikog signala. Upravo je prilagodba
zadatak transpondera. Dakle, radi se o komponenti koja ima jedan optiki ulaz i jedan
optiki izlaz, no isto tako valja imati na umu da se u transponderu ulazni signal pretvara
prvo u elektrinu domenu, te nakon prilagodbe ponovno pretvara u optiku domenu.

multiplekser. Zadatak je multipleksera da vie ulaznih signala s razliitih vlakana, te na


razliitim valnim duljinama, utisne u jedno optiko vlakno. Sadri vie optikih ulaza, te
jedan optiki izlaz.

demultiplekser. Komponenta funkcije komplementarne onoj u multipleksera. Jedan


optiki ulaz, te vie optikih izlaza. pojaalo. Pojaava optiki signal. Jedan optiki ulaz i
jedan optiki izlaz.

pretvara valnih duljina. Valna duljina nosioca signala se pretvara u drugu. Jedan optiki
ulaz i jedan optiki izlaz.

komutator (prospojnik). Izvodi prostorno prospajanje signala. Sadri vie optikih ulaza i
izlaza, a signal se prespaja s odreenog optikog ulaza (vlakna) na odreeni optiki izlaz
(vlakno). vlakno.

Ovim popisom je samo utvrena funkcija pojedinog elementa unutar sveoptike mree. Iako se
odnosi meu komponentama mogu naslutiti oni nisu formalno definirani. Taj korak slijedi iz
znanja, tj. poznavanja njihove funkcije.

11.3 Prijenos znanja u C++


Nakon to je usvojeno sve potrebno znanje, potrebno ga je izraziti u C++ jeziku koristei objektni
pristup koji se sastoji (u ovom naem stupnju razmatranja) od tri dijela:
1. odnosi izmeu komponenata,
2. atributi komponenata, i
3. metode (funkcije) komponenata.
Modeliranje elemenata ovakve mree u znaajnoj mjeri ovisi o potrebnoj razini apstrakcije, a
koja opet ovisi o zadatku koja naa aplikacija mora obaviti. Ukoliko je na cilj dizajn mree,
razina apstrakcije e biti najvia (ili najnia, ovisno o pogledu). U tom sluaju e koliina
informacije koje objekti moraju sadravati u velikoj mjeri biti reducirana. Primjerice, svakoj
komponenti je potrebno pridruiti cijenu, moda raspoloivost, odnosno komplementarnu
vrijednost kvara ili sl. U sluaju da nam je cilj simulacija takve mree, razina apstrakcije je
minimalna.

60

C++ i osnove objektno orijentiranog dizajna


Svakoj komponenti je potrebno pridruiti mnotvo atributa, koji e opisivati fizikalno ponaanje
odgovarajueg objekta. Primjeri atributa su gustoe slobodnih nosioca u odreenim energetskim
stanjima, faktori refleksivnosti, fizike dimenzije poluvodikih komponenata i sl.

11.4 Odnosi meu komponentama (taksonomija)


Najjednostavnije (gledajui po vremenu koje bi utroili na razmiljanje) bi bilo napraviti onoliko
klasa koliko ima komponenata i u njih poslagati potrebne atribute i metode. Takav pristup bi
imali u ne-objektnim jezicima kao to je C.
Bolje rjeenje je koritenje inherentnih prirodnih svojstava fizikih komponenata. One naime nisu
u potpunosti nezavisne, tovie sve se mogu svesti na jednu ili vie istih openitijih pojmova.
Kaemo da se sve mogu naslijediti od klase koja je semantiki (sadrajno) na vioj razini
apstrakcije.
Ovakav pristup je bolji jer se prirodni odnosi direktno preslikavaju u programski jezik
olakavajui razvoj sloenijih programa, odnosno dodavanje elemenata koji nisu moda u prvom
koraku bili vani, ili su se pojavili tijekom vremena. Novi tipovi multipleksera e sigurno imati
ulaze i izlaze, kao i pouzdanost i cijenu. Te parametre je koristei objektni pristup lako naslijediti
od ve definiranih klasa, a nove atributi se moraju samo dodati postojeima. Time se eliminira
potreba za ponovnim pisanjem svih atributa i metoda koje moda ve postoje.

11.5 Bazna klasa


Dizajn stabla nasljeivanja obino se zapoinje definiranjem najopenitijeg pojma (klase) koja
sadri atribute i metode koji e biti zajedniki svim klasama koje iz nje elimo naslijediti.
Najee se radi o klasi koja nedovoljno definira bilo koji stvarni element (u naem sluaju
komponentu u mrei), pa niti nema smisla stvarati objekte takve klase. U ovom sluaju bi najvii
stupanj apstrakcije ako se ograniimo na fizikalne elemente mree bio element. Definirajmo
stoga klasu Element s atributima koji e biti zajedniki za sve ostale elemente mree:
class Element{
private:
long Cijena; //cijena elementa
double VjKvara; //vjerojatnost kvara elementa
public:
void setCijena(long unos){Cijena=unos;}
long getCijena() {return Cijena;}
void setVjKvara(double unos){VjKvara=unos;}
double getVjKvara(){return VjKvara;}
Element(void) : Cijena(0), VjKvara(1){}
Element(long cj, double vj) : Cijena(cj), VjKvara(vj){}
};

Oito je da su cijena i vrijeme kvara nezaobilazni atributi svakog elementa.

11.6 Specificiranje nasljeivanja


Svaki element mree se moe svrstati u jednu od dvije skupine:
1. optiki element, i
2. elektroniki element.
Definirajmo stoga dvije nove klase koje e naslijediti baznu klasu i njezine atribute.
Openito se nasljeivanje izvodi na sljedei nain:

61

C++ i osnove objektno orijentiranog dizajna


class imeIzvedeneKlase : pravo_pristupa imeOsnovneKlase;

Pravo pristupa odreuje nain preslikavanja prava pristupa atributima i metodama bazne klase.
Iz bazne klase nasljeujemo dvije klase:
class Oelement : public Element{ //optiki element
protected:
int BrOUlaza; //0 do beskonano
int BrOIzlaza; //0 do beskonano
public:
void setBrOUlaza(int ulaz){BrOUlaza=ulaz;}
void setBrOIzlaza(int izlaz){BrOIzlaza=izlaz;}
};
class Eelement : public Element{ //elektroniki element
protected:
int BrEUlaza; //0 do beskonano
int BrEIzlaza; //0 do beskonano
public:
void setBrEUlaza(int ulaz){BrEUlaza=ulaz;}
void setBrEIzlaza(int izlaz){BrEIzlaza=izlaz;}
};

11.7 Nasljeivanje i prava pristupa


Pravo pristupa odreuje nain preslikavanja prava pristupa atributima i metodama bazne klase po
sljedeem pravilu: klase Oelement i Eelement javno (public) nasljeuju baznu klasu. To znai
da e sve javne metode (Set, Get) biti dio javnog suelja objekata ovih klasa, tj. moi e im
se pristupiti iz programa:
Oelement oe;
oe.setCijena(1000);

Svi privatni atributi i metode osnove klase (Cijena, VjKvara) ostaju nedostupne i preko objekta:
izvedene klase i unutar klase:
oe.Cijena=1000; //greka
class Oelement : public Element{

public:
void postavi(long ulaz){cijena=ulaz;} //greka iako je cijena dio
klase Oelement, ona nije izravno vidljiva unutar klase
}
Tip
Pravo pristupa u osnovnoj klasi
public
protected private
nasljeivanja
public
protected private
public
protected
private

protected

protected

private

private

private

private

11.8 Nasljeivanje i relacije


Prilikom nasljeivanja sluili smo se relacijom biti izmeu klase Element i Eelement, koristei
injenicu da je svaki elektroniki element ujedno i element u openitom (generikom) smislu.
Osim relacije biti, mogua je i relacija sadri koja moe donijeti probleme ukoliko se realizira
relacijom biti. Primjer takve pogreke bi bilo nasljeivanje tipa:
class Tranzistor{
private:
long cijena;

62

C++ i osnove objektno orijentiranog dizajna


double VjKvara;
};
class Eelement : public Tranzistor{}

Ovakva implementacija dovodi kasnije do velikih problema jer nije zadovoljen uvjet stroge
hijerarhije. Naime tranzistor nije semantiki vii pojam od elektronikog elementa (kao dijela
mree), ve je jedan od gradivnih dijelova elektronikog elementa:
class Eelement {
Tranzistor skupTran[100]; //skup tranzistora u (jako) pojednostavljenom
Eelementu

};

Trei mogui odnos je koristiti, kada neka apstrakcija (klasa) koristi drugu apstrakciju (klasu), ali
ju ne posjeduje.

11.9 Viestruko nasljeivanje


Definirajmo sada dvije nove klase Opojacalo koja nasljeuje Oelement i Oprijemnik koja
nasljeuje i Oelement i Eelement, jer se radi o komponenti koja je istovremeno i optika i
elektronika :
class Opojacalo : public Oelement{
private:
double Pojacanje;
double SirinaSpektra;
public:
void setPojacanje(double unos){pojacanje=unos;}
void setSS(double unos){SirinaSpektra=unos;}
};
class Oprijemnik : public Oelement, Eelement{
private:
double Osjetljivost;
public:
Oprijemnik(double unos) : Osjetljivost(unos) {}
void setOsjetljivost(double unos){Osjetljivost=unos;}
};

Preko objekata klase Oprijemnik mogue je javnim pristupiti metodama klasa Oelement i
Eelement:
class Oprijemnik op;
op.setBrOUlaza(10);
op.setBrEIzlaza(15);

Pogledajmo u grafikom obliku kako izgleda genealogija naeg nasljeivanja:

Slika 9 Genealogija nasljeivanja

63

C++ i osnove objektno orijentiranog dizajna


Sada je jasno da klasa Oprijemnik sadri dvije klase Element. Iako je ovaj nain formalno
prihvatljiv i nee se prijaviti pogreka prilikom prevoenja, problemi e nastati ako se pokua
pristupiti bilo kojoj javnoj metodi ili atributu klase koja je dva ili vie puta naslijeena na istu
izvedenu klasu:
class Oprijemnik op;
op.setCijena(100);

Nastaje dvosmislenost (ambiguity) jer nije jasno kojoj se metodi pristupa (iako su one iste).
Viestruko nasljeivanje iste klase treba izbjegavati i zbog injenice da u tom sluaju nisu
podrane ugraene konverzije.

11.10 Virtualna osnovna klasa


Virtualna osnovna klasa rjeava spomenuti problem dvosmislenosti kada se jedna klasa ukljui
vie puta u izvedenu klasu. Osnovna klasa se pretvara u virtualnu navoenjem rijei virtual pri
nasljeivanju:
class Oelement : virtual
public Element{}
class Eelement : virtual
public Element{}
class Oprijemnik : public Oelement,
public Eelement{}

Ovim nasljeivanjem se dobiva struktura prikazana na slici. Osnovna klasa Element sadrana je
samo jednom u klasi Oprijemnik. Kako unutar objekta izvedene klase postoji samo jedna
osnovna virtualna klasa, njezinim se lanovima moe pristupati bez opasnosti od nejasnoa.
Virtualne osnovne klase se inicijaliziraju konstruktorom u najdalje izvedenoj klasi. Svi
konstruktori pozvani prije toga se zanemaruju.

Slika 10 Genealogija nasljeivanja uz primjenu virtualnog nasljeivanja

11.11 Karakteristike virtualnog nasljeivanja


Mehanizam virtualnog nasljeivanja se ostvaruje pomou pokazivaa. Dijelovi izvedenog objekta
koji se odnose na elemente osnovne klase ne sadre te elemente ve pokazivae na memorijski
prostor koji je zajedniki svim podobjektima koji su virtualno naslijedili tu klasu. Problemi
ovakvog mehanizma nastaju kada se virtualno nasljeuje ista klasa s razliitim pravom pristupa:
class Oelement : virtual private Element{}
class Eelement : virtual public Element{}
class Oprijemnik : public Oelement, public Eelement{}

64

C++ i osnove objektno orijentiranog dizajna


Razrjeavanje prava pristupa elementima klase Element se obavlja po principu prevladavanja
javnog puta do nekog lana:
Oprijemnik op;
op.setCijena(1000); //prevladava javni pristup

Drugo pravilo je pravilo dominacije koje kae da uvijek prevladava lan koji je definiran u
hijerarhijski blioj klasi:
class Oelement : virtual public Element{}
class Eelement : virtual public Element{
public:
void setCijena(long ulaz){cout<<Ne mogu!<<endl;}
}
class Oprijemnik : public Oelement, public Eelement{}
class Oprijemnik op;
op.setCijena(1000); //ispis Ne mogu! jer definicija funkcije setCijena u
Eelement prekriva definiciju u Element koja se takoer nezavisno nasljeuje
preko Oelement

11.12 Pristup lanovima izvedenih klasa


lanovima izvedenih klasa se preko njihovog objekta pristupa kao i lanovima osnovnih klasa:
Opojacalo op;
op.setPojacanje(1000.1); //pristup metodi definiranoj u izvedenoj klasi
op.setBrOUlaza(5); //pristup metodi osnovne klase

Pristup metodama osnovne klase se moe ostvariti i preko scope resolution operatora:
op.Oelement::setBrOUlaza(5); //pristup metodi osnovne klase

Nije potrebno eksplicitno navoditi podruje definicije pozvane metode ili atributa osim ako u
osnovnim klasama postoji dva ili vie lanova istog imena (tako se ipak ne moe izbjei virtualno
nasljeivanje) ili ako je u izvedenoj klasi definirana metoda ili atribut istog imena koji uvijek
prekriva onaj iz osnovne klase:
class Opojacalo : public Oelement{
public:
void setBrOUlaza(ulaz){cout<<Greka!<<endl;}

};
Opojacalo op;
op.setBrOUlaza(100); // Greka!
op.Oelement:setBrOUlaza(100); //ispravno postavljanje u osnovnoj klasi

11.13 Ugraene pretvorbe i nasljeivanje


Jedno od najsnanijih svojstava koje omoguuje veliku fleksibilnost koda su ugraene pretvorbe
koje se mogu saeti u 4 pravila:
1. objekt izvedene klase moe se implicitno pretvoriti u objekt javne osnovne klase,
2. referenca na objekt izvedene klase moe se implicitno pretvoriti u referencu na objekt
javne osnovne klase,
3. pokaziva na objekt izvedene klase moe se implicitno pretvoriti u pokaziva na objekt
javne osnovne klase. Pokaziva na objekt izvedene klase moe se implicitno pretvoriti na
pokaziva void* i obratno ali uz eksplicitnu pretvorbu, te
4. pokaziva na lan izvedene klase moe se implicitno pretvoriti u pokaziva na lan javne
osnovne klase.
65

C++ i osnove objektno orijentiranog dizajna


Navedene pretvorbe su jasne ako uzmemo u obzir na svaki izvedeni objekt sadri podobjekt
osnovne klase. Ako se radi o pokazivaima dolazi jednostavno do pomaka pokazivanja:
Opojacalo *op = new Opojacalo;
Oelement *oe=op;

Prilikom pridruivanja oe=op provodi se implicitna konverzija tako da oe pokazuje na


memorijski prostor koji pripada klasi Oelement. Oito je da obratna konverzija mora biti
eksplicitna, jer osnovni objekt ne mora sadravati elemente izvedenog i moe doi do pristupa
nerezerviranom memorijskom prostoru.
Pojacanje
SirinaSpektra

dio klase Opojacalo

BrojOulaza
BrojOizlaza

dio klase Oelement

cijena
vjKvara

dio klase Element

11.14 Konstruktori i destruktori izvedenih klasa


Konstruktor izvedene klase zaduen je za inicijalizaciju elemenata definiranih u izvedenoj klasi,
dok elemente osnovne klase inicijalizira konstruktor osnovne klase. Ukoliko nije drugaije
naznaeno poziva se podrazumjevani konstruktor osnovne klase. Konstruktor osnovne klase se
moe i eksplicitno pozvati u konstruktoru izvedene klase ukoliko mu je potrebno prenijeti
inicijalizacijsku vrijednost:
class Oelement : public Element{

public:
Oelement (int brUl, int brIz, long cj, double vj) : brOUlaza(brUl),
brOIzlaza(brIz), Element(cj, vj);
};

Ukoliko se izostavi definicija konstruktora izvedene klase, automatski se definira podrazumjevani


konstruktor koji poziva podrazumijevane konstruktore osnovne(ih) klase(a) koji u tom sluaju
mora(ju) postojati.
Redoslijed poziva konstruktora:
1. konstruktori osnovnih klasa pozivaju se prema redoslijedu iz liste izvoenja klasa,
2. svaki se konstruktor izvodi u redoslijedu navoenja objekata (a ne inicijalizacijske liste),
te
3. na kraju se izvodi konstruktor izvedene klase.
Ovakav redoslijed pozivanja konstruktora uvijek vrijedi bez obzira na prevodioc. Prilikom
unitavanja objekata pozivaju se destruktori izvedene klase koji unitavaju samo dio definiran u
izvedenoj klasi, te destruktori osnovnih klasa koji unitavaju dijelove koji pripadaju osnovnim
klasama. Poziv destruktora obratan je pozivima konstruktora.

11.15 Podruje pretraivanja


Kod nasljeivanja dolazi do ugnjeivanja podruja deklaracija. Prilikom poziva metode ili
pristupa varijabli, prvo se pretrauje podruje klase kojoj objekt pripada (Opojacalo), a zatim

66

C++ i osnove objektno orijentiranog dizajna


nadreenih klasa (Oelement i zatim Element). Treba zato biti oprezan priliko redefinicije
funkcijskog lana. Svaka redefinicija prekriva definiciju u nadreenoj klasi, pa ak i ako je samo
koriten isti identifikator funkcije, a razliiti potpisi. To je posljedica injenice da nasljeivanje
nije vrsta preoptereenja:
class Opojacalo : public Oelement{

public:
void setBrOUlaza(void){cout<<Greka!<<endl;}
};
Opojacalo op;
op.setBrOUlaza(100); //greka funkcija nadreene klase prekrivena je
funkcijom istog imena, ali razliitog potpisa

Obje funkcije mogu biti ukljuene ponavljanjem definicije funkcije istog potpisa kao u osnovnoj
klasi:
class Opojacalo : public Oelement{
public:
void setBrOUlaza(int ulaz){Oelement::setBrOUlaza(ulaz);}
void setBrOUlaza(void){cout<<Greka!<<endl;}
};

Element
Oelement

redoslijed
pretraivanja
podruja

Opojacal

11.16 Ugnijeeni tipovi


Ugnijeeni tipovi koriste se za realizaciju relacije biti dio od i nemaju veze s nasljeivanjem, ali
se ovdje navode zbog potpunosti. Za ugnijeene tipove vrijede sva pravila nasljeivanja i
pristupa:
class Oprijemnik : public Oelement, public Eelement{

protected:
class Stabilizator {
double Faktor;
public:
double getFaktor(void);
};

Za pristup elementima i metodama potrebno je koristiti scope resolution operator:


Oprijemnik::Stabilizator::getFaktor(void){return Faktor;}

Ugnijeena klasa se moe naslijediti:


class IzvStab : public Oprijemnik::Stabilizator{}

11.17 Klase kao argumenti funkcija (ugraene konverzije)


Principi implicitne ugraene pretvorbe najvie dolaze do izraaja prilikom prijenosa objekata kao
argumenta funkcije. Do konverzije ne dolazi ako se tipovi objekata (stvarni i formalni parametri)
u potpunosti podudaraju ili ako se radi o trivijalnoj konverziji objekt ->referenca na objekt:

67

C++ i osnove objektno orijentiranog dizajna


void f(Opojacalo &opFormalni);
Opojacalo opStvarni;
f(opStvarni); //trivijalna konverzija

Ukoliko tipovi parametara ne odgovaraju provodi se ugraena konverzija i to na hijerarhijski


najblii tip:
void f(Element el);
void f(Oelement el);
void f(Eelement el);
void f(void *el);

Opojacalo opo;
Oprijemnik opr;
f(opo); //konverzija na Oelement
f(opr); //greka nejasnoa oko poziva konverzije
f((Eelement) opr); //eksplicitna konverzija na Eelement
void * se pri tom smatra najudaljenijim lanom u hijerarhiji.

11.17.1 Klase kao argumenti funkcija (korisnike konverzije)


Pri prijenosu parametara mogue je obaviti i korisniku konverziju konstruktorom ako se ne
pronae preoptereena funkcija s argumentom na kojeg je mogua ugraena konverzija. Pri
pozivu korisnike konverzije se (ako je to potrebno) moe pozvati ugraena konverzija tipa, ali
samo jednom. Uzastopni poziv dvije korisnike konverzije nije mogu:
void f2(Oelement el);
float a=10;
f2(10);

U gornjem pozivu se provodi ugraena konverzija float -> double, pa double -> ugraena
konverzija preko konstruktora -> objekt Oelement.

11.18 Nasljeivanje i preoptereeni operatori


Preoptereeni operatori su zapravo obini funkcijski lanovi i za njih vrijede ista pravila kao i za
ostale funkcijske lanove:
class Element{

public:
int operator==(double a);
};
class Oelement : public Element{

public:
int operator==(int a);
};
Oelement oe;
int s=(oe==3.4); //greka

Operator pridruivanja = se ne nasljeuje, jer je potrebno inicijalizirati cijeli objekt, a ne samo dio
koji pripada osnovnoj klasi. Inicijalizacija podrazumijevanim operatorom pridruivanja
(kopiranje bit po bit) moi e se provesti ukoliko postoji korisnika pretvorba pridruene
vrijednosti u tip objekta konstruktori su takoer iskljueni iz nasljeivanja, pa e gore spomenute
konverzije konstruktorom biti mogue samo uz eksplicitno definiranje konstruktora s jednim
parametrom u izvedenoj klasi.

11.19 Polimorfizam i tipovi vezivanja

68

C++ i osnove objektno orijentiranog dizajna


Polimorfizam je uz enkapsulaciju i nasljeivanje osnovna karakteristika objektno orijentiranog
jezika, a omoguuje definiranje operacija koje su ovisne o tipu. Mehanizmi ugraenih konverzija
omoguuju da se svakom objektu izvedene klase pristupi preko objekta osnovne klase proirimo
osnovnu klasu Element metodom Aktiviraj():
class Element{

public:
void Aktiviraj(void) {}
};

Metoda Aktiviraj() ne radi nita u osnovnoj klasi jer njezina implementacija ovisi o
konkretnom elementu i ne moe se openito definirati:
class Oelement : public Element{

public:
void Aktiviraj(void) {implementacija}
};

Ugraenim konverzijama mogue su sljedee pretvorbe:


Oelement *oe=new Oelement;
Element *e=oe;
oe->Aktiviraj(); //poziva konkretnu implementaciju iz Oelement
e->Aktiviraj(); //poziva implementaciju iz Oelement koja ne radi nita

Vidljivo je da na ovaj nain nismo postigli oekivan rezultat, a to je da se preko pokazivaa tipa
osnovne klase, a koji pokazuje na objekt izvedene klase ipak moe pozvati metoda izvedene, a ne
osnovne klase. Pokaziva na osnovni objekt je samo nain promatranja na neki konkretni
izvedeni objekt i on ne mijenja objekt na koji pokazuje u programskom smislu, niti mijenja
smisao objekta na koji pokazuje u semantikom smislu.
Svaki optiki element moemo nazvati elementom (mree) bez da promijenimo smisao, a time i
metode nad optikim elementom. Izloena potreba predstavlja smisao polimorfizma.
Polimorfizam se ne moe ostvariti na prethodni nain, jer se radi o statikom ili ranom
povezivanju (static binding). Kod statikog povezivanja prevodiocu je dostupan jedino tip
pokazivaa pomou kojeg se poziva objekt (Element), a ne i tip na koji taj pokaziva pokazuje
(Oelement). Pozvana metoda e stoga biti pozvana iz klase koja odgovara tipu pokazivaa.
Rjeenje problema lei u promjeni pogleda na nain izvoenja metode umjesto da se metoda
odreuje prilikom povezivanja (to je mogue preko tipa, ali ne i zadovoljavajue), bolje je
ostaviti odreivanje metode za vrijeme izvoenja (run-time) kada e biti poznat tip objekta na
koji pokaziva pokazuje. Zajedno s objektom je potrebno pohraniti i tip objekta, a prilikom
prevoenja prevoditelj mora stvoriti kod koji e te informacije proitati i pozvati odgovarajuu
funkciju. Takav pristup se naziva dinamikim ili kasnim povezivanjem (dynamic binding).

11.20 Dinamiko povezivanje i virtualni funkcijski lanovi


Dinamiko povezivanje se moe nainiti runo navoenjem tipa u osnovnoj klasi koji e
odreivati tip na koji pokazuje pokaziva osnovne klase.
C++ nudi elegantnije rjeenje za ostvarivanje dinamikog povezivanja pomou virtualnih
funkcijskih lanova koji se deklariraju navoenjem kljune rijei virtual:
class Element{

public:

69

C++ i osnove objektno orijentiranog dizajna


virtual void Aktiviraj(void) {}
};
class Oelement : public Element{

public:
virtual void Aktiviraj(void);
};

Prilikom definicije virtualnog funkcijskog lana izostavlja se rije virtual:


void Oelement::Aktiviraj(void){implementacija}

Svi lanovi koji nisu navedeni kao virtualni povezuju se statiki i nazivaju statikim funkcijskim
lanovima.
Oelement *oe=new Oelement;
Element *e=oe;
e->Aktiviraj(); //poziva se funkcija Aktiviraj() iz klase Oelement

Kada je neki funkcijski lan deklariran kao virtualan, on je automatski virtualan i u svim
izvedenim klasama, pa nije potrebno eksplicitno navoditi kljunu rije virtual.
lanovi sa statikim pozivom mogu biti redeklarirani kao virtualni u izvedenim klasama.

11.21 Pozivi virtualnih funkcijskih lanova


Za sve virtualne funkcijske lanove prevodilac rezervira u memoriji tablicu vtable u koje ih
pohranjuje i vee uz odgovarajui objekt pomou pokazivaa *vptr. Prilikom poziva virtualnog
funkcijskog lana preko pokazivaa tipa osnovne klase nee doi do poziva funkcije iz osnovne
klase, ve e se iz tablice vtable pozvati implementacija koja odgovara izvedenom tipu. Ovakav
nain pozivanja funkcijskih lanova zahtijeva dodatno procesorsko vrijeme i memorijski prostor
u usporedbi sa statikim povezivanjem.
Kod statikog povezivanja uz objekt su bili direktno vezani atributi, dok su se metode pozivale
prema tipu koji se odreivao prema tipu pokazivaa koji je pokazivao na objekt. Zato je pristup
atributima bio dobar, a metodama neodgovarajui poziv virtualne funkcije e biti virtualan ako se
vri preko pokazivaa ili reference:
Oelement oe;
Element *pokE=&oe, &refE=oe;
pokE->Aktiviraj();
refE.Aktiviraj(); //oba poziva su virtualna
vptr

vtable

atributi objekta

Aktiviraj

Postoje tri sluaja kada se poziv virtualnog funkcijskog lana obavlja statiki:
1. poziv preko objekta klase, jer se pri prevoenju tono zna tip za koji se lan poziva:
Oelement oe;
oe.Aktiviraj();

2. eksplicitno navoenje klase iz koje se poziva funkcijski lan preko scope resolution
operatora:
oe.Element::Aktiviraj();

Eksplicitno navoenje podruja izvedene klase nije mogue ako se radi o pokazivau tipa
osnovne klase zbog nepoznavanja objekta na koji pokaziva pokazuje prilikom
prevoenja:
70

C++ i osnove objektno orijentiranog dizajna


Element *pokOe=&oe;
pokOe->Oelement::Aktiviraj(); //greka

Statiko pozivanje se odnosi samo na onaj lan koji je eksplicitno naveden. Svi lanovi
koji se pozivaju iz njega zadravaju svoj nain povezivanja:
Oe.Element::Aktiviraj(); //sve funkcije koje bi se eventualno
pozvale iz Aktiviraj() zadrale bi svoje povezivanje

3. poziv funkcije iz konstruktora (poziv virtualne funkcije moe rezultirati pristupom jo


neinicijaliziranom dijelu objekta) ili destruktora (poziv virtualne funkcije moe rezultirati
pristupom ve unitenom dijelu objekta).

11.22 iste virtualne funkcije


Klasa Element zapravo nema neko stvarno znaenje i nema smisla definirati objekt te klase.
Takve klase koje samo definiraju javno suelje nazivaju se apstraktnim klasama (abstract
classes). To javno suelje biti e specificirano tek u izvedenim klasama.
Funkcije koje slue samo za definiranje javnog suelja preporuljivo je specificirati kao iste
virtualne funkcije (pure virtual functions). Apstraktne klase (termin C++ jezika) sadre barem
jednu istu virtualnu funkciju:
class Element{

public:
virtual void Aktiviraj(void)=0; //Aktiviraj je ista virtualna funkcija
};

Sada smo i formalizirali u C++ jeziku injenicu da nema smisla definirati objekt klase Element.
Takav pokuaj rezultirati e pogrekom prilikom prevoenja. Reference i pokazivae tipa
apstraktne klase je naravno mogue definirati (polimorfizam!). iste virtualne funkcije se
normalno nasljeuju i mogu se definirati u izvedenoj klasi (time te funkcije prestaju biti istima).
Ukoliko se to ne uini i izvedena klasa postaje apstraktnom. Poziv iste virtualne funkcije koja
nije definirana zavrava pogrekom.

11.23 Virtualni destruktori


Smisao virtualnih destruktora je (ispravno) unitavanje objekta izvedene klase pozivom operatora
delete na pokazivau osnovne klase koja pokazuje na izvedenu:
Oelement *oe=new Oelement;
Element *e=oe;
delete e;

Ukoliko bi destruktor imao statiko povezivanje gornji poziv bi rezultirao pozivom destruktora
bazne klase (jer je to tip pokazivaa e). Rjeenje je proglaavanje destruktora virtualnim u baznoj
klasi Element:
class Element{

public:
virtual ~Element(void){}
}

Destruktori svih izvedenih klasa e automatski biti virtualni, pa to nije potrebno posebno
specificirati rijeju virtual. U principu je dobro uvijek destruktor apstraktne klase proglasiti
virtualnim jer destruktor sa statikim povezivanjem tu niti nema smisla.

71

C++ i osnove objektno orijentiranog dizajna


Ukoliko se klasa ne nasljeuje nema smisla koristiti rije virtual, jer ona samo proiruje objekt
pokazivaem vptr na tablicu virtualnih funkcija i zauzima u memoriji prostor za tablicu vtable.

11.24 Polimorfizam i proirivost koda


Sada kada je objanjen princip polimorfizma pokaimo na naem primjeru njegovu praktinu
upotrebu. Definirajmo funkciju koja obavlja neku operaciju nad optikim pojaalima:
class Opojacalo : public Oelement{

public:
virtual void Aktiviraj(void) {implementacija}
};
void f(Element *oPoj){

oPoj->Aktiviraj();
}

U funkciju je mogue prenijeti bilo koji objekt bilo koje izvedene klase iz apstraktne osnovne
klase Element. Nakon nekog vremena odluimo poboljati model i podijeliti skup optikih
pojaala i skup optikih prijamnika. Optika pojaala se naime mogu podijeliti u dvije skupine:
erbijem dopirana optika pojaala (EDFA), te poluvodika optika pojaala (SOA) koja su
istovremeno i elektroniki elementi. Isto tako, u optici se kao optiki prijemnici najee koriste
dvije vrste poluvodikih dioda: lavinske (APD, Avalanche Photo Diode) i PIN fotodiode.
Deklaracije novih funkcija:
class EDFA : public Opojacalo{
public:
virtual void Aktiviraj(void){implementacija}
};
class SOA : public Opojacalo, public Eelement{
public:
virtual void Aktiviraj(void){implementacija}
};
class APD : public Oprijemnik{
public:
virtual void Aktiviraj(void){implementacija}
};
class PIN : public Oprijemnik, public Eelement{
public:
virtual void Aktiviraj(void){implementacija}
};

Dodavanje novih elemenata bi kod neobjektno orijentiranih jezika nuno prouzroilo potrebu
pisanja novih funkcija koje moda nad tim elementima rade istu operaciju kao i nad ve
postojeima. Ovdje proirenje stabla nasljeivanja lanovima koji su naslijeeni iz ve postojeih
ne donosi nikakvu potrebu za mijenjanjem koda. Prilikom prijenosa objekata novih klasa u
funkciju f obaviti e se konverzija na tip apstraktne osnovne klase Element, a poziv funkcije
Aktiviraj() e uredno pozvati implementaciju danu u novim klasama.
Moda ovo nakon poznavanja mehanizma ugraene konverzije i dinamikog vezivanja ne
predstavlja neku novost, ali sjetimo se da prilikom pisanja funkcije f nismo niti slutili da emo
imati nove klase EDFA, SOA, APD i PIN a da implementacija ipak radi zahvaljujui koritenju
funkcije Aktiviraj() koja je dio javnog suelja, i zato ima smisla na svim izvedenim klasama.
Proirivost C++ koda lei dakle u injenici da je jednom napisane algoritme nad elementom
univerzalnog suelja (definiranog u apstraktnoj osnovnoj klasi) mogue primjenjivati na sve

72

C++ i osnove objektno orijentiranog dizajna


objekte koji to suelje dijele (koji su iz te apstraktne osnovne klase naslijeeni). Na slici 11
prikazana je taksonomija do sada izvedenih elemenata.

Slika 11 Taksonomija nakon dodavanja novih klasa

11.25 Primjeri zadataka


11.25.1 Listing datoteke List.h
#include <iostream.h>
typedef unsigned long DWord;
class lAtom
{
protected:
int data1;
int data2;
lAtom* Next;
lAtom* Prev;
public:
lAtom(int some1, int some2=0);
~lAtom(void);
int getData1(void);
int getData2(void);
int setData1(int some);
int setData2(int some);
lAtom* GetNext(void);
lAtom* GetPrev(void);
lAtom* SetNext(lAtom* some);
lAtom* SetPrev(lAtom* some);
};
//lista
class list
{
protected:
lAtom* Head;
DWord cnt;
public:
list(void);
~list(void);
DWord getCnt(void);
lAtom* RemoveHead(void);
lAtom* RemoveTail(void);
lAtom* RemoveElem(int some1, int some2=0);

73

C++ i osnove objektno orijentiranog dizajna


lAtom* AddToList(int some1, int some2=0);
void printAll(void);
};

11.25.2 Listing datoteke List.cpp


#include "list.h"
lAtom::lAtom(int some1, int some2){
data1=some1;
data2=some2;
Next=NULL;
Prev=NULL;
};
lAtom::~lAtom(void){
};
int lAtom::getData1(void){
return data1;
};
int lAtom::getData2(void){
return data2;
};
int lAtom::setData1(int some){
int retVal=data1;
data1=some;
return retVal;
};
int lAtom::setData2(int some){
int retVal=data2;
data2=some;
return retVal;
};
lAtom* lAtom::GetNext(void){
return Next;
};
lAtom* lAtom::GetPrev(void){
return Prev;
};
lAtom* lAtom::SetNext(lAtom* some){
lAtom* retVal=Next;
Next=some;
return retVal;
};
lAtom* lAtom::SetPrev(lAtom* some){
lAtom* retVal=Prev;
Prev=some;
return retVal;
};
list::list(void){
cnt=0;
Head=NULL;
};
list::~list(void){

74

C++ i osnove objektno orijentiranog dizajna


if(Head==NULL ||cnt==0) return;
lAtom* p;
while(Head!=NULL){
p=Head->GetNext();
delete Head;
Head=p;
}
Head=NULL;
cnt=0;
};
DWord list::getCnt(void){
return cnt;
};
lAtom* list::AddToList(int some1, int some2){
if(Head==NULL){
Head=new lAtom(some1, some2);
cnt++;
return Head;
}
lAtom* p=Head;
while(p->GetNext()!=NULL){
p=p->GetNext();
}
lAtom* pom=new lAtom(some1, some2);
p->SetNext(pom);
pom->SetPrev(p);
cnt++;
return pom;
};
lAtom* list::RemoveHead(void){
if(Head==NULL) return NULL;
lAtom* retVal=Head;
if(cnt==1){
cnt=0;
Head=NULL;
return retVal;
}
Head=retVal->GetNext();
Head->SetPrev(NULL);
cnt--;
return retVal;
};
lAtom* list::RemoveTail(void){
if(Head==NULL) return NULL;
lAtom* retVal=Head;
if(cnt==1){
cnt=0;
Head=NULL;
return retVal;
}
lAtom* p=Head;
while(p->GetNext()!=NULL){
p=p->GetNext();
}
p->GetPrev()->SetNext(NULL);
cnt--;

75

C++ i osnove objektno orijentiranog dizajna

};

return p;

lAtom* list::RemoveElem(int some1, int some2){


if(Head==NULL) return NULL;
lAtom* p=Head;
while(p->GetNext()!=NULL && p->getData1()!=some1 && p>getData2()!=some2){
p=p->GetNext();
}

};

if(p->getData1()==some1 && p->getData2()==some2){


if(cnt==1)
Head=NULL;
else if(Head==p){
p->GetNext()->SetPrev(NULL);
Head=p->GetNext();
}else if(p->GetNext()==NULL) //tail
p->GetPrev()->SetNext(NULL);
else{
p->GetPrev()->SetNext(p->GetNext());
p->GetNext()->SetPrev(p->GetPrev());
}
cnt--;
return p;
}
return NULL;

void list::printAll(void){
lAtom* p=Head;
if(p==NULL) {
cout << "List is empty" << endl;
return;
}
while(p!=NULL){
cout<<p->getData1()<<"("<<p->getData2()<<")"<<" ";
p=p->GetNext();
}
cout << endl;
return;
};

1.

Implementirajte rep cijelih brojeva organiziran po FIFO principu.

Metode: dolazak elementa, odlazak elementa


Preoptereene operatorske funkcije:
<< ispis repa
[] dohvat elementa repa na zadanoj poziciji (indeksiranje kao u poljima)
- (unarni) dohvat trenutnog promatranog elementa u repu

iterator repa:
++ kretanje kroz rep (sljedei element)
-- kretanje kroz rep (prethodni element)

76

C++ i osnove objektno orijentiranog dizajna


Naputak: zadatak rijeite koritenjem mehanizma nasljeivanja iz bazne klase i koritenjem
implementiranih osnovnih metoda.
2.

Implementirajte stog cijelih brojeva.

Metode: stavljanje elementa (push), skidanje elementa (pop)


Preoptereene operatorske funkcije:
<< ispis stoga
[] dohvat elementa stoga na zadanoj poziciji (indeksiranje kao u poljima)
- (unarni) dohvat trenutnog promatranog elementa u stogu

iterator stoga:
++ kretanje kroz stog (sljedei element)
-- kretanje kroz stog (prethodni element)

Naputak: zadatak rijeite koritenjem mehanizma nasljeivanja iz bazne klase i koritenjem


implementiranih osnovnih metoda.
3.
Implementirajte niz cijelih brojeva kojem se dinamiki mijenjaju dimenzije (npr. korisnik
moe pristupiti bilo kojem lanu bez deklaracije duine polju se automatski poveava duina da
moe realizirati zahtjev). Zadatak rijeiti uz minimalan broj dealokacija (slijedna struktura)
Metode: pristup lanu (getAt(int)), upisivanje vrijednosti lana (putAt(int, int))
Preoptereene operatorske funkcije:
<< ispis polja
[] dohvat elementa polja na zadanoj poziciji (indeksiranje kao u klasinim poljima)
- (unarni) dohvat trenutnog promatranog elementa u polju

iterator polja:
++ kretanje kroz polje (sljedei element)
-- kretanje kroz polje (prethodni element)

Naputak: zadatak rijeite koritenjem mehanizma nasljeivanja iz bazne klase i koritenjem


implementiranih osnovnih metoda.
4.
Implementirati izlazni spremnik ATM switcha. elije imaju CLP polja s vrijednostima 1
i 0. Vrijednost 1 ima vei prioritet. Sve elije imaju svoj cjelobrojni jedinstveni ID.
Metode: primanje nove elije, slanje elije na link, broj elija u repu
Preoptereene operatorske funkcije:
<< ispis ID svih elija koje su u spremniku

77

C++ i osnove objektno orijentiranog dizajna


[] dohvat ID elije na zadanoj poziciji u spremniku (indeksiranje kao u poljima)
- (unarni) dohvat ID trenutno promatrane elije u spremniku

iterator kompozicije:
++ kretanje kroz spremnik (sljedea elija)
-- kretanje kroz kompoziciju (prethodna elija)

Naputak: zadatak rijeite koritenjem mehanizma nasljeivanja iz bazne klase i koritenjem


implementiranih osnovnih metoda.
Napomena: elije veeg prioriteta imaju i vei prioritet pri izlasku.
5.
HT je naruio program za implementaciju pristupa E1 mux sustavu (30 korisnikih
kanala + sinkronizacijski + signalizacijski kanal). Ukoliko je sustav zauzet odbijeni poziv se
stavlja u listu ekanja. Oslobaanjem jednog od kanala, taj kanal odmah zauzima poziv koji je
najdue ekao. Svaki poziv ima svoj jedinstveni cjelobrojni ID.
Metode: dolazak novog poziva, raskid poziva, ispis postotka zauzetosti sustava.
Preoptereene operatorske funkcije:
<< ispis ID svih poziva koji su u listi
[] dohvat ID poziva na zadanoj poziciji u listi (indeksiranje kao u poljima)
- (unarni) dohvat ID trenutno promatranog poziva u listi

iterator liste:
++ kretanje kroz listu (sljedei poziv)
-- kretanje kroz listu (prethodni poziv)

Naputak: zadatak rijeite koritenjem mehanizma nasljeivanja iz bazne klase i koritenjem


implementiranih osnovnih metoda.
6.
Implementirajte spremnik servera koji obrauje zahtjeve koji mogu imati prioritete 0,1,2.
U jednom trenutku obrauje se samo jedan zahtjev. Ukoliko doe zahtjev prioriteta 2 za vrijeme
obrade nieg prioriteta tada se on hitno obrauje, a trenutno obraivani zahtjev ide na pocetak
spremnika.
Metode: dolazak, odlazak, ispis broja paketa u spremniku
Preoptereene operatorske funkcije:
<< ispis ID svih paketa koje su u spremniku
[] dohvat ID paketa na zadanoj poziciji u spremniku (indeksiranje kao u poljima)
- (unarni) dohvat ID trenutno promatranog paketa u spremniku

iterator spremnika:
++ kretanje kroz spremnik (sljedei zahtjev)

78

C++ i osnove objektno orijentiranog dizajna


-- kretanje kroz spremnik (prethodni zahtjev)

Naputak: zadatak rijeite koritenjem mehanizma nasljeivanja iz bazne klase i koritenjem


implementiranih osnovnih metoda.
7.
Implementirajte sustav koji se sastoji od procesora i ogranienog spremnika (maksimalni
broj elemenata m). Procesor u jednom trenutku obrauje najvie 1 paket (zahtjev).Prioriteti
zahtjeva su 0 i 1. Ako zahtjev prioriteta 0 naleti na pun spremnik on e biti odbijen. Ako zahtjev
prioriteta 1 naleti na pun spremnik tada e on doi na mjesto zadnje primljenog paketa prioriteta
0 koji e biti izbaen.
Metode: dolazak, odlazak, ispis broja
Preoptereene operatorske funkcije:
<< ispis ID svih paketa koje su u spremniku
[] dohvat ID paketa na zadanoj poziciji u spremniku (indeksiranje kao u poljima)
- (unarni) dohvat ID trenutno promatranog paketa u spremniku
iterator spremnika:
++ kretanje kroz spremnik (sljedei paket)
-- kretanje kroz spremnik (prethodni paket)
Naputak: zadatak rijeite koritenjem mehanizma nasljeivanja iz bazne klase i koritenjem
implementiranih osnovnih metoda.

79

C++ i osnove objektno orijentiranog dizajna

12 Predloci (templates)
Teme obraene u ovom dijelu:

to su predloci (templates)
Predloci funkcija
Predloci klasa
Definicija predloka klase
Instanciranje predloka klase i deklaracija objekta
Specijalizacija funkcijskih lanova
Predloci, statiki lanovi i ugnjeivanje
Predloci i prijatelji klasa
Predloci i nasljeivanje

12.1 to su predloci (templates)?


Predloci (templates) relativno su kasno postali dio C++ sintakse i nisu podrani od starijih
prevodioca. Upotreba predloaka vrlo je iroka i moe se koristiti u svim sluajevima kada tip
ulaznih podataka nije poznat (odnosno ne spada u mehanizam ugraene ili korisnike pretvorbe),
a moe se podvesti pod neki zajedniki algoritam.
Predloci se openito dijele na:
1. predloke funkcija, i
2. predloke klasa.

12.2 Predloci funkcija


Preoptereenje funkcija dozvoljava upotrebu istog imena za opis algoritama koji obavljaju srodne
operacije nad razliitim tipovima podataka. Svaka od preoptereenih funkcija mora imati svoju
definiciju premda se moda radi o istom algoritmu nad drugaijim tipom.
Predloci funkcija (function templates) omoguuju pisanje definicije jedne funkcije, pri emu
se tip podataka ostavlja neodreen (otvoren) i odreuje se prilikom poziva funkcije.
12.2.1 Definicija predloka funkcije
Predloak se definira na sljedei nain:
template <class tip1, class tip2, >
povratni_tip imeFunkcije(lista_argumenata){}

Definicija predloka funkcije poinje kljunom rijei template. U <> zagradama navodi se lista
formalnih parametara koja ne moe biti prazna. Prije svakog formalnog parametra navodi se rije
class iza kojeg se navodiidentifikator. Vrijednost identifikatora odreuje se prilikom prevoenja i
zamjenjuje nekim ugraenim ili korisnikim tipom to ovisi o pozivu funkcije:
template <class tip> tip manji(tip a, tip b){
return a<b ? a : b;
}
void main(void){
int c=4;
int d=manji(3,c);
}

80

C++ i osnove objektno orijentiranog dizajna


Prevodioc e iz gornjeg poziva stvoriti funkciju
int manji(int a, int b){
return a<b ? a : b;
}

Ime identifikatora predloka funkcije mora biti jedinstveno u listi jedne funkcije, ali se moe
ponavljati kod razliitih funkcija. Identifikator se moe upotrijebiti proizvoljno mnogo puta (i
nijedanput). Identifikator moe odreivati povratni tip funkcije.
template <class tip> tip f(int a, tip b);

Mogue je koristiti modifikatore & i * da bi se dobila referenca i pokaziva na argument.


Dozvoljeno je eksplicitno navoenje tipa formalnog parametra u pozivajuem kodu, pri emu <>
zagrade moraju biti neposredno uz ime funkcije:
int a=manji<int,int>(1,2);

Umjesto rijei class prije imena formalnog argumenta dozvoljeno je koristiti i kljunu rije
typename:
template <typename tip>
tip f(tip a);

Dozvoljeno je koritenje podrazumijevanih parametara predloka:


template <class t1, class t2=int>
t1 f(t2 a);

Iza navoenja rijei template moe slijediti deklaracija ili definicija funkcije. U tom pogledu
funkcije s predlocima se ponaaju kao obine funkcije.
12.2.2 Implicitno instanciranje predloaka
Instanciranjem predloaka navode se ugraeni ili korisniki tipovi koji zamjenjuju formalne
parametre i omoguuju prevodiocu stvaranje koda sa stvarnim parametrima implicitno
instanciranje dozvoljava odreivanje parametara iz tipa prenesenih argumenata, pri emu se dio
argumenata moe i eksplicitno navesti:
template <class t1, class t2, class t3> t1 f(t2 a, t3 b);

float b=5.5;
double a=f<double>(4,b); //t1 je zamijenjen eksplicitno s double,
dok su t2 i t3 zamijenjeni implicitno s int i float

Pri odreivanju tipova u listi parametara ne primjenjuju se nikakva pravila konverzije. Ako se
formalni argument u listi argumenata pojavljuje vie puta, tada u pozivu funkcije na tim mjestima
mora stajati tono isti tip:
template <class t>
int f(t a, t b);

int a=1, b=2;


int c=f(a, b);

12.2.3 Eksplicitno instanciranje predloaka


Eksplicitni instanciranjem predloaka deklariraju se sve inaice predloka koje e se koristiti u
programu eksplicitnim navoenjem tipa, pri emu je potrebno navesti puni potpis funkcije. Da bi
prevodioc mogao instancirati eljene funkcije iz cijelog skupa proptereenih funkcija:
template <class t1, class t2>
t1 f(t2 *a, int b);

81

C++ i osnove objektno orijentiranog dizajna


template double f<double, char>(char*, int);
template int f<int, double>(double*, int);

Ako je lista parametara predloka funkcije prazna, a kao formalni parametar predloka se koristi
podrazumjevani tip, potrebno je pri pozivu navesti prazne <> ako zadravamo podrazumjevani
tip:
template <class t=float>
t f(void);

double a=f<>();

Kao formalni parametar moe se navesti i konstanta kojom funkcija barata kao da je prenesena
argumentom:
template <class t, int brElem>
void f(void){t b[brElem];}

void f<float, 10> f(); //svaki poziv s drugaijom vrijednosti brElem uzrokuje
instanciranje nove funkcije to dovodi do bujanja koda (code bloat)

12.2.4 Preoptereivanje predloaka funkcija


Predloci funkcija se mogu preopteretiti, ali se potpisi funkcija moraju razlikovati po broju i/ili
tipu argumenata:
template <class t>
int f(t a);
template <class t>
int f(t a, t b);
template <class t>
int f(t *a);

Koritenjem mehanizma preoptereenja mogue je stvoriti specijalizacije predloaka funkcija, tj.


definirati tijelo funkcije za tip koji se ne moe svesti pod ope pravilo (iji se algoritam razlikuje
od ostalih sluajeva) tako da se navede uobiajena definicija funkcije, ali s imenom predloka:
template manji <class t> t manji(t a, t b){
return a<b ? a : b;
}
char *manji(char *a, char *b){//specijalizacija predloka
return strcmp(a, b)<0 ? a : b;
}

12.3 Predloci klasa


Omoguuju definiranje opih klasa koje se konkretiziraju stvarnim tipom. Najee se koriste za
kontejnerske klase koje pohranjuju nizove objekata i nad njima. Vre operacije koje ne ovise o
tipu tih objekata.
Cilj upotrebe predloka klasa je olakavanje odravanja i proirivanja koda. Programer ima
gotove algoritme i podatke koji zajedno ine neku logiku cjelinu, ali se primjenjuju na razliite
tipove. Umjesto kopiranja koda onoliko puta koliko ima tipova na koje ih primjenjuje, moe
jednostavno primijeniti predloak klase. Time ispravak pogreaka postaje puno jednostavniji jer
je kod samo na jednom mjestu, a ne ponavlja se na nekoliko mjesta samo zbog promjene tipa.
Predloci klasa omoguuju i upotrebu samo jednog imena bez obzira na tip elemenata te klase.
Tako se klasa koja obavlja funkciju stoga moe zvati stog bez obzira da li se na stog spremaju
cjelobrojni ili realni brojevi.
12.3.1 Definicija predloka klase
82

C++ i osnove objektno orijentiranog dizajna


Definicija predloka klase slina je definiciji predloka funkcije:
template <class t1, class t2, >
class imeKlase;

Lista parametara ne smije biti prazna, a parametar predloka moe biti i izraz:
template <class t1, class t2, int brElem> class imeKlase;

Klase definirane kao predloci obavezno se moraju eksplicitno instancirati navoenjem


parametara u <> zagradama:
imeKlase<int, double>

Unutar klase se identifikator imeKlase moe navesti bez parametara:


template <class t> class imeKlase{
t var;
imeKlase *pok;
public:
imeKlase *f(t arg);
};

12.3.2 Instanciranje predloka klase i deklaracija objekta


Instanciranje predloka klase obavlja se pri deklaraciji objekta pri deklaraciji objekta obavezno se
navodi puni naziv klase koji ukljuuje i parametre unutar <> zagrada:
imeKlase<int, double> obj;

Sa instanciranim predlokom klase moe se postupati kao s obinom klasom:


imeKlase<int, double> obj1[10];
const imeKlase<int, double> obj2;
extern imeKlase<int, double> obj3;

Pojedine instance neke klase definirane predlokom nije doputeno mijeati jer predstavljaju
razliite tipove. Nekad je potrebno instancirati predloak unutar definicije drugog predloka, pri
emu je mogue koristiti parametar predloka koji se definira kao stvarni parametar predloka
kojeg se instancira:
template <class t>
void f(imeKlase<t> &a){}

Klasu je mogue i eksplicitno instancirati:


template class imeKlase<int>;

ili samo neki njezin funkcijski lan:


template class imeKlase<int>::f(int, int);

12.3.3 Specijalizacija funkcijskih lanova


Funkcijske lanove predloaka klasa ponekad je potrebno specijalizirati za neki konkretni tip
specijalizacija se provodi navoenjem konkretnog tipa u listi formalnih argumenata:
template <class t> class klasa{
public:
t f(t) {return t};
};
klasa<int>::f(int a){return a-1} //posebno instanciranje funkcije f za tip int

83

C++ i osnove objektno orijentiranog dizajna


Specijalizacija predloka se moe navesti samo nakon navoenja opeg predloka ako se
instancira specijalizirani primjerak klase, potrebno je definirati sve funkcijske lanove
eksplicitno.
12.3.4 Predloci, statiki lanovi i ugnjeivanje
Pri definiranju mogue je navesti statike lanove pri emu e svaka instanca tog predloka imati
svoj zasebni skup statikih lanova. Predloke klasa koji nemaju smisla izvan predloaka neke
druge klase mogue je ukljuiti u tu klasu, pri emu se prilikom instanciranja klase sadrioca
instanciraju sve klase unutar nje:
template <class t> class klasa{
public:
template <class t> class klasa2{}
};

Klasa klasa je sada parametrizirana s dva argumenta i njezina inicijalizacija glasi:


klasa<int>::klasa2<double> obj;

12.3.5 Predloci i prijatelji klasa


postoje tri naina na koji se jedan predloak moe nainiti prijateljem drugog
predloka:
1. predloak se deklarira kao prijatelj druge funkcije i klase koja nije predloak:
class a{};
void f(void);
template <class t> class b{
friend class a; //klasa a i funkcija f prijatelji su svih
friend void f; //instanciranih klasa predloka b
};

2. svaka klasa jednog predloka vee se uz tono jednu klasu drugog predloka vezano
prijateljstvo (bound template friendship):
template<class t> class c{
friend class b<t>;
};

3. svaka klasa koja proizlazi iz predloka vee se sa svim klasama nekog drugog predloka
nevezano prijateljstvo (unbound template friendship):
template<class tip> class d{friend class b<t>;}{
template<t>
friend c<t>;
};

12.3.6 Predloci i nasljeivanje


Postoje tri naina nasljeivanja predloaka:
1. predloak klase slui kao osnovna klasa za izvoenje konkretne klase koja nije predloak.
Osnovna klasa pri tom mora biti parametrizirana konkretnim tipovima:
class nasljednik : osnovna<int, double> {}

2. predloak klase se izvodi iz obine klase:


template <class t> class nasljednik : tip_pristupa osnovna{} //sve
varijante klase nasljednik imaju po jedan neparametrizirani podobjekt klase
osnovna

84

C++ i osnove objektno orijentiranog dizajna


3. nasljeivanje u kojem se predloak klase izvodi iz nekog drugog predloka. Pri tome je
mogue iz svake varijante osnovne klase izvesti jednu varijantu izvedene klase:
template <class t> class nasljednik : tip_pristupa osnovna<t>{}

ili izvui predloak iz tono odreene varijante osnovne klase:


template <class t> class nasljednik : tip_pristupa osnovna<int>{}

12.4 Primjeri zadataka


1.
Modificirajte postojee klase list i atom tako da lista ima potpunu funkcionalnost
(ispravan rad svih metoda) neovisno o klasi objekata koje sadri (koristiti predloke). Nadopunite
listu metodama sort i find ije su deklaracije dane u datoteci list.h. Implementirajte klasu vektor
(3 dimenzije) ije ete objekte stavljati u listu.
Metode: konstruktor, destruktor, konstruktor kopije
Preoptereene operatorske funkcije:
<< ispis komponenti vektora
== jednakost vektora
= pridruivanje vektora
<, > usporedba vektora (po apsolutnoj vrijednosti)

Napomena: Metoda sort koristi operatore (<, >), a metoda find operator ==
2.
Modificirajte postojee klase list i atom tako da lista ima potpunu funkcionalnost
(ispravan rad svih metoda) neovisno o klasi objekata koje sadri (koristiti predloke). Nadopunite
listu metodama sort i find ije su deklaracije dane u datoteci list.h. Implementirajte klasu
kompleksni ije ete objekte stavljati u listu.
Metode: konstruktor, destruktor, konstruktor kopije
Preoptereene operatorske funkcije:
<< ispis Re i Im dijela
== jednakost kopleksnih brojeva
= pridruivanje
<, > usporedba (po apsolutnoj vrijednosti)

Napomena: Metoda sort koristi operatore (<, >), a metoda find operator ==
3.
Modificirajte postojee klase list i atom tako da lista ima potpunu funkcionalnost
(ispravan rad svih metoda) neovisno o klasi objekata koje sadri (koristiti predloke). Nadopunite
listu metodama sort i find ije su deklaracije dane u datoteci list.h. Implementirajte klasu string
ije ete objekte stavljati u listu.
Metode: konstruktor (char *), destruktor, konstruktor kopije
Preoptereene operatorske funkcije:
<< ispis stringa

85

C++ i osnove objektno orijentiranog dizajna


== jednakost
= pridruivanje
<, > usporedba stringova (po abecednom redu)
Napomena: Metoda sort koristi operatore (<, >), a metoda find operator ==

4.
Modificirajte postojee klase list i atom tako da lista ima potpunu funkcionalnost
(ispravan rad svih metoda) neovisno o klasi objekata koje sadri (koristiti predloke). Nadopunite
listu metodama sort i find ije su deklaracije dane u datoteci list.h. Implementirajte klasu
razlomak ije ete objekte stavljati u listu.
Metode: konstruktor (brojnik, nazivnik), destruktor, konstruktor kopije
Preoptereene operatorske funkcije:
<< ispis
== jednakost
= pridruivanje
<, > usporedba

Napomena: Metoda sort koristi operatore (<, >), a metoda find operator ==
5.
Modificirajte postojee klase list i atom tako da lista ima potpunu funkcionalnost
(ispravan rad svih metoda) neovisno o klasi objekata koje sadri (koristiti predloke). Nadopunite
listu metodama sort i find ije su deklaracije dane u datoteci list.h. Implementirajte klasu trokut
ije ete objekte stavljati u listu.
Metode: konstruktor, destruktor, konstruktor kopije
Preoptereene operatorske funkcije:
<< ispis stranica trokuta
== jednakost (sukladnost)
= pridruivanje
<, > usporedba (obzirom na povrinu)

Napomena: Metoda sort koristi operatore (<, >), a metoda find operator ==
6.
Modificirajte postojee klase list i atom tako da lista ima potpunu funkcionalnost
(ispravan rad svih metoda) neovisno o klasi objekata koje sadri (koristiti predloke). Nadopunite
listu metodama sort i find ije su deklaracije dane u datoteci list.h. Implementirajte klasu celija
ije ete objekte stavljati u listu.
Metode: konstruktor (char * sadrzaj, double vrijemeDolaska) , destruktor, konstruktor kopije
Preoptereene operatorske funkcije:
<< ispis sadraja, vremena dolaska

86

C++ i osnove objektno orijentiranog dizajna


== jednakost (po sadraju)
= pridruivanje
<, > usporedba (po vremenu)

Napomena: Metoda sort koristi operatore (<, >), a metoda find operator ==
7.
Modificirajte postojee klase list i atom tako da lista ima potpunu funkcionalnost
(ispravan rad svih metoda) neovisno o klasi objekata koje sadri (koristiti predloke). Nadopunite
listu metodama sort i find ije su deklaracije dane u datoteci list.h. Implementirajte klasu
sinusoida ije ete objekte stavljati u listu.
Metode: konstruktor (amplituda, frekvencija, pocKut), destruktor, konstruktor kopije
Preoptereene operatorske funkcije:
<< ispis podataka o sinusoidi
== jednakost (nema faznog pomaka, ista frekvencija , ista amplituda)
= pridruivanje objekta objektu
<, > usporedba (prema frekvenciji)

Napomena: Metoda sort koristi operatore (<, >), a metoda find operator ==

87

C++ i osnove objektno orijentiranog dizajna

13 Imenici (namespaces)
Teme obraene u ovom dijelu:

to su imenici?
Deklaracija imenika
Pristup elementima imenika
Deklaracija i direktiva using
Klase i deklaracija using

13.1 to su imenici?
Prilikom razvoja sloenog programa moe doi do ponavljanja imena identifikatora npr.
ukljuivanjem datoteka zaglavlja koje sadre definicije, a koje su pisali razliiti programeri
(zagaenje globalnog podruja).
Imenici slue za uklanjanje identifikatora (imena) varijabli, funkcija, klasa iz globalnog podruja
imena, tako to sadre logiki povezane grupe identifikatora koji se po potrebi mogu ukljuiti u
globalno podruje.

13.2 Deklaracija imenika


Deklaracija imenika obavlja se kljunom rijei namespace:
namespace imeImenika{
lista identifikatora (imena varijabli i klasa, deklaracije funkcija,
itd.)
}
namespace covjek{
int godiste;
float visina;
float tezina;
class podaciMUP;
int daLiJeJeo(int sekOdPonoci) ;
}

Podaci unutar imenika mogu biti deklarirani i definirani. Imenik moe biti ponovno deklariran,
ali se ta deklaracija smatra nadopunom prijanje:
namespace covjek{
int celav;
}

Ime imenika mora biti jedinstveno u podruju pojavljivanja. Imenici se mogu pojaviti u
globalnom podruju ili unutar drugog imenika.

13.3 Pristup elementima imenika


Elementima imenika pristupa se koritenjem operatora za razluivanje podruja :: :
covjek::visina=186.3;
int odg=covjek::daLiJeJeo(15231);

Unutar imenika nije potrebno navoditi podruje jer se ono podrazumijeva:


namespace covjek{
void popravi(void){
godiste+=10;
}

88

C++ i osnove objektno orijentiranog dizajna


}

lanovima imenika bez naziva pristupa se bez eksplicitnog navoenja imenika:


namespace {
int a; int b;
}
int a; //a u globalnom podruju
b=1; //b iz imenika
::a=2; //a iz globalnog podruja
a=1; //greka

13.4 Deklaracija i direktiva using


Identifikator iz nekog imenika (deklaracija using) ili cijeli imenik (direktiva using) mogue je
uvesti u podruje imena pomou kljune rijei using:
using covjek::visina; //uvoenje identifikatora visina iz imenika covjek
using namespace covjek; //uvoenje cijelog imenika
using ima funkciju deklaracije navedenih identifikatora. Nakon uvoenja identifikatora u

podruje imena, s tim identifikatorom se moe koristiti kao da je u tom podruju normalno
deklariran:
using covjek::tezina;
tezina=65;

Direktivom using deklariraju se samo oni identifikatori koji su do tog mjesta u kodu ukljueni u
imenik. Uvoenjem imena preoptereene funkcije uvode se sve instance te funkcije.

13.5 Klase i deklaracija using


U klasu se koritenjem using mogu ukljuiti elementi neke druge klase, ali samo ako su oni
dostupni klasi u koju se ukljuuju i ako je klasa u koju se ukljuuju izvedena iz klase iji se
elementi ukljuuju:
class osnovna{
public:
void f(int a){cout<<a<<endl;}
};
class izvedena:public osnovna{
public:
using osnovna::f;
void f(char *s){cout<<s<<endl;}
};

Bez koritenja using definicija funkcije f u izvedenoj klasi prebrisala bi definiciju funkcije f iz
osnovne klase. Na ovaj nain omogueno je koritenje mehanizma preoptereivanja, tj. pozivi
obje funkcije iz izvedene klase su mogui:
izvedena obj;
obj.f(1); //f iz osnovne klase
obj.f(C++); //f iz izvedene klase

89

C++ i osnove objektno orijentiranog dizajna

14

Iznimke

Teme obraene u ovom dijelu:

to su iznimke
Blokovi pokuaja i hvatanja iznimaka
Identifikacija iznimaka
Tijek obrade iznimaka
Liste moguih iznimaka

14.1 to su iznimke?
Iznimke (exceptions) su situacije u kojima program ne moe nastaviti izvoenje normalnim
tokom, ve je potrebno prekinuti dretvu i izvoenje nastaviti nekim drugim odsjekom programa
(koji e tu iznimku obraditi).
Umjesto izrade vlastitih mehanizama obrade iznimaka, jezik C++ prua ugraeni mehanizam za
rukovanje iznimkama (exception handling). U tom ugraenom sustavu iznimka (exception) se
definira kao dogaaj u raunalu koji onemoguava normalan nastavak izvoenja programa, te
zahtjeva posebnu obradu. Pri detektiranju takve iznimke program podie iznimku (raise an
exception), izvoenje programa se prekida, a iznimka se predaje rutini za oporavak od iznimke
(exception recovery routine).

14.2 Blokovi pokuaja i hvatanja iznimaka


Ideja je razbijanje C++ koda u blokove pokuaja (try block) koji sadre potencijalno opasne
operacije. Blokovi pokuaja se specificiraju tako da se navede kljuna rije try iza koje se u
vitiastim zagradama navode problematine instrukcije.
Svaki blok pokuaja mora biti praen barem jednim blokom hvatanja (catch block) koji se
specificira kljunom rijei catch:
try{

blok pokuaja
}
catch(parametar){
blok hvatanja
}

Za podizanje (bacanje) iznimke koristi se kljuna rije throw uz koju se navodi parametar koji
ukazuje na tip iznimke i omoguuje pozivanje koda za obradu te vrste iznimke:
throw 100;
throw Evo iznimke!;

14.3 Identifikacija iznimaka


Poeljno je definirati posebnu klasu koja e sadravati opis iznimke i na taj nain omoguiti
jednostavnije pisanje catch blokova:
class iznimkaKlase{
char *opis;
public:
iznimkaKlase(char *ulaz):opis(new char[strlen(ulaz)+1]){
strcpy(opis,ulaz);}

90

C++ i osnove objektno orijentiranog dizajna


iznimkaKlase(iznimkaKlase &ref):opis(new
char[strlen(ref.opis)+1]){strcpy(opis,ref.opis);}
~iznimkaKlase{delete [] opis;}
};

throw iznimkaKlase(Nesto krivo vezano uz objekt klase Klasa);

catch(iznimkaKlase &izn){}
catch blok sada prima samo iznimke koje kao poruku alju objekt klase iznimkaKlase. Na taj

nain omogueno je jednostavnije razgraniavanje blokova za obradu razliitih iznimki.

14.4 Tijek obrade iznimaka


Unitavaju se svi privremeni i lokalni objekti koji su stvoreni u bloku u kojem je doli do
iznimke, a stvara se novi objekt (prethodni primjer) koji se prenosi prvom catch bloku iza bloka
pokuaja koji prihvaa baenu iznimku. Nakon zavretka bloka hvatanja iznimke unitava se
privremeni objekt koji je sadravao podatke o iznimci, a kontrola se prenosi na prvu naredbi iza
zadnjeg bloka hvatanja.
Ako u bloku pokuaja nije dolo do iznimke preskau se svi blokovi hvatanja iza tog bloka. Ako
baena iznimka ne odgovara ni jednom catch bloku koji slijede iza tog bloka pokuaja, ona se
prenosi u prvi nadreeni pokuajni blok do mjesta obrade iznimke e se unititi svi lokalni i
privremeni objekti stvoreni do mjesta bacanja iznimke, odnosno unutar pokuajnog bloka (ili
ugnijeenih blokova). Taj postupak se zove odmatanje stoga.
Dinamika memorija se nee osloboditi nakon bacanja iznimke. Stoga ju je potrebno obrisati u
bloku hvatanja ili osigurati destruktor.
Ako je kao parametar bloku navedena referenca, blok hvatanja moe promijeniti proslijeeni
objekt. Ako on dalje prosljeuje objekt, nainjene promjene biti e vidljive u proslijeenim
blokovima hvatanja.

14.5 Liste moguih iznimaka


Pomou liste moguih iznimaka funkcija odreuje koje sve iznimke moe baciti lista moguih
iznimaka navodi se iza liste parametara funkcije pomou kljune rijei throw:
povratni_tip imeFunkcije(lista_argumenata) throw(tip1, tip2, ){}

lista moguih iznimaka moe biti i prazna:


povratni_tip imeFunkcije(lista_argumenata) throw(){}

Lista moguih iznimaka sadri samo one tipove koji mogu biti baeni izvan funkcije, bilo da su
generirani u samoj funkciji ili nekoj pozvanoj funkciji unutar nje.
int f(int a) throw(int){
try{
throw(Iznimka);
}
catch(char *) {
throw 0; //samo 0 moe biti baena izvan funkcije
}
}

Lista moguih iznimaka nije dio potpisa funkcije.

91

C++ i osnove objektno orijentiranog dizajna

15

Pretprocesorske naredbe

Teme obraene u ovom dijelu:

Pojam pretprocesorskih naredbi


Pretprocesor, prevoditelj i poveziva
Naredbe #include, #define i #undef
Uvjetno prevoenje
Uvjetno prevoenje, assert i pronalaenje pogreaka
Operatori za rukovanje nizovima

15.1 Pojam pretprocesorskih naredbi


Uporaba pretprocesorskih naredbi je vrlo esta u programskom jeziku C, no u C++ je bitno
smanjena zbog dodatnih mehanizama.
U C++ se pretprocesorske naredbe uglavnom koriste za ukljuivanje datoteka s deklaracijama
funkcija i klasa i uvjetno prevoenje dijelova programa, dok su definiranje konstanti i makro
funkcija zamijenili mehanizmi predloaka funkcija, umetnute funkcije i preoptereenje funkcija.
Pretprocesorske naredbe:
#pragma
#error

#line
#undef

#define
#include

#endif
#else

#elif
#ifndef

#ifdef
#if

Pretprocesorske naredbe uzrokuju modifikaciju koda neposredno pred prevoenje i bitno


oteavaju nalaenje pogreaka.
14.2. Pretprocesor, prevoditelj i poveziva

Slika 12 Pretvorba C++ programa u izvrni kod

15.2 Naredbe #include, #define i #undef


Naredbom #include provodi se tekstovno povezivanje vie datoteka u jednu datoteke je mogue
ukljuiti iz tekueg direktorija:
#include moj.h

ili iz podrazumijevanog direktorija:

92

C++ i osnove objektno orijentiranog dizajna


#include <iostream.h>

Naredbom #define definiraju se vrijednosti simbola ili makro imena


#define GENIJE I, me & myself
#define PI 3.14

Sve pojave rijei GENIJE i PI e se prilikom prevoenja zamijeniti definiranim zamjenama.


Vrijednost definicije moe se promijeniti novom naredbom #define:
#define GENIJE Homer Simpson

ili naredbom #undef kojom se ponitava makro ime


#undef GENIJE

Upotreba makro imena za konstante se izbjegava u C++ jer se time ne rezervira memorijska
lokacija ve samo definira zamjena, pa je debug programa otean. Umjesto toga koriste se
konstantni tipovi:
const double pi=3.14;

15.3 Uvjetno prevoenje


Makro naredbe za uvjetno prevoenje omoguuju da se u prevoenje ukljue neki dijelovi koda
ovisno o vrijednosti nekog logikog izraza. Postoje tri naredbe za ispitivanje uvjetnog prevoenja
#if, #ifdef i #ifndef, pri emu svaka od njih mora zavravati sa #endif. Mogue je koritenje
vie neovisnih grana unutar bloka proizvoljnim brojem grana #elif i maksimalno jednom
granom #else:
#define GODINA PRVA;

#if GODINA==PRVA char *tesko=fizika2;


#elif GODINA==DRUGA char *tesko=elektronika1;
#else char *tesko=none;
#endif

Makronaredbom #ifdef ispituje se da li je neko ime definirano. Komplementarna makronaredbi


#ifdef je naredba #ifndef:
#ifndef GODINA
char *tesko=Ne studira!;

15.4 Uvjetno prevoenje,

assert

i pronalaenje pogreaka

Ujetno prevoenje se esto koristi pri razvoju programa za kontrolne ispise. Te je spise kasnije
lako maknuti uklanjanjem makro imena:
#define NDEBUG //NoDebug
#ifndef NDEBUG
cout<<Program je u fazi debugiranja<<endl;
#else
cout<<Program je u fazi prodaje<<endl;
#endif

Ustandardnoj datoteci assert.h nalazi se deklaracija makro funkcije assert koja rovjerava da li
je ispunjen neki uvjet, te prekida izvrenje programa ako uvjet nije spunjen:
assert(uvjet);

Definiranjem simbolike konstante NDEBUG svi pozivi funkcije assert zamjenjuju se null
naredbom.

93

C++ i osnove objektno orijentiranog dizajna

15.5 Operatori za rukovanje nizovima


Operatori # i ## nemaju nikakve veze s pretprocesorom ve slue za rukovanje nizovima.
Operator # pretvara simboliko ime varijable u znakovni niz:
int varA=5;
cout<<Vrijednost <<#varA<< je <<varA<<endl; //vrijednost varA je 5

Operator ## slui za stapanje simbolikih imena:


int nova ## Var; //int novaVar;

94

C++ i osnove objektno orijentiranog dizajna

16

Organizacija koda

Teme obraene u ovom dijelu:

Zato je organizacija koda potrebna


Datoteke zaglavlja
Povezivanje
Specifikatori static i extern

16.1 Zato je organizacija koda potrebna


Kod sloenijih programa poeljno je kod podijeliti u vie datoteka iz nekoliko razloga:
1. promjenom podatka u jednoj datoteci treba prevesti samo tu datoteku, jer druge
nepromijenjene datoteke nije potrebno prevoditi. Poveziva povezuje novo prevedenu
datoteku i prije prevedene datoteke u izvrni kod,
2. prevoenje velikog koda zahtjeva veliku simboliku tablicu naziva objekata i funkcija u
izvornom kodu i njihove veze s adresom u objektnom kodu,
3. preglednost definicije klasa je najbolje navesti u zasebnoj datoteci to olakava njihovo
ukljuivanje u neki budui program, te
4. timski rad najjednostavnije je da svaki programer pie svoj dio koda u zasebnoj
datoteci.
Datoteke (moduli) koje sainjavaju jedan program se na kraju poveu. Pretprocesorskom
naredbom #include u glavnu datoteku (modul) koji sadri funkciju main():
#include prva.cpp
#include druga.h
void main(void){

16.2 Datoteke zaglavlja


u posebne module (datoteke zaglavlja) koje se ukljuuju u sve ostale datoteke
korisno je staviti deklaracije koje omoguuju da klase i funkcije definirane u jednom
modulu budu vidljive i upotrebljive iz svih modula
u deklaracije zaglavlja najee se stavlja:
1. deklaracije (nestatikih) klasa i struktura (definicije ovih lanova se navode samo u
datoteci izvornog koda ako nisu s unutarnjim povezivanjem)
class kompl{
int re, im;
public:
int Re();
int Im();
}

2. deklaracije funkcija
extern int f(double, char*);

3. definicije funkcija i objekata s unutarnjim povezivanjem (umetnute funkcije i simbolike


konstante),
95

C++ i osnove objektno orijentiranog dizajna


4. deklaracije globalnih podataka koji moraju biti vidljivi iz razliitih modula:
extern float verzija;

5. definicije konstanti koje moraju biti vidljivi iz razliitih modula:


const double pi=3.14;

6. pobrojenja:
enum dobriAuti { audi, lada, folcvagen TAS}

7. makrodefinicije i makrofunkcije:
#define PI 3.14

U datoteke zaglavlja ne treba stavljati definicije funkcija i objekata datoteke zaglavlja najee
imaju ekstenziju .h (header) iako to nema nikakvu ulogu pri prevoenju. Datoteke zaglavlja
nemaju funkcije main() one ne pozivaju funkcije, niti ne inicijaliziraju objekte klasa i
struktura.

16.3 Povezivanje
Datoteke ukljuene pretprocesorskom naredbom #include ukljuuju se na poetak datoteke i
normalno prevode u objektni kod. Objektni kod podijeljen u vie razliitih datoteka povezuje
poveziva (linker).
Odgovarajua definicija funkcije ili tipa se trai tek prilikom povezivanja (prevodioc je preveo
kod na temelju deklaracija) pa tu mogu nastati greke ako potpisi deklarirane i definirane funkcije
nisu isti.
Identifikatori (objekti i funkcije) koji su prilikom povezivanja vidljivi i u drugim modulima imaju
vanjsko povezivanje (external linkage) te moraju biti jedinstveni na cijelom podruju (ne mogu
postojati dvije funkcije istog potpisa).
Svi globalni identifikatori datoteke imaju vanjsko povezivanje. Identifikatori s unutarnjim
(inline) povezivanjem vidljivi su samo unutar bloka u kojem su definirani. Identifikatori s
vanjskim povezivanjem zaklanjaju isto ime identifikatora s unutarnjim povezivanjem (bez
javljanja greke), osim u bloku gdje je identifikator s unutarnjim povezivanjem definiran.

16.4 Specifikatori static i extern


Kljunom rijei static ispred deklaracije objekta ili funkcije eksplicitno se odreuje interno
povezivanje. Globalne objekte i funkcije je preporuljivo uiniti statikima osim ako ne postoji
potreba da oni budu vidljivi iz drugih modula. Kljunom rijei extern se podrazumijevano
unutarnje povezivanje identifikatora pretvara u vanjsko.
Pri navoenju rijei extern mogue je objekt inicijalizirati i tada se radi o definiciji (u izvornom
modulu za taj objekt):
extern const float pi=3.14

Ako se inicijalizacija ispusti radi se o deklaraciji identifikatora te se prevodiocu ukazuje da se


definicija (a time i rezervacija memorije) tog objekta nalazi negdje drugdje:
extern const float pi; //definicija varijable pi se nalazi u nekoj drugoj
datoteci

96

C++ i osnove objektno orijentiranog dizajna

17

C i C++

Teme obraene u ovom dijelu:

Usporedba C i C++
Slinost sintakse C i C++
Razlike sintakse C i C++
Novi mehanizmi u C++
Nove kljune rijei u C++
C++ kao objektno orijentirani jezik

17.1 Usporedba C i C++


C++ jezik je dugo ostao zanemarivan od C programera zbog predrasuda kao to je sporost
izvravanja koda i puno vea kompleksnost C++ programa u odnosu na njegov C ekvivalent. Nije
postojala potreba za prelazak u novi jezik ija se sintaksa vrlo malo razlikuje od dobro poznate C
sintakse pomou koje je i onako bilo mogue sve rijeiti.
C i C++ se mogu usporeivati na dvije razine:
1. sintaktika razina, i
2. idejna razina.
Kod sintaktike razine zaista e se pronai malo razlika izmeu C i C++, no pristup
programiranju je kod C i C++ potpuno razliit.

17.2 Slinost sintakse C i C++


Kljuni razlog brzog rasta popularnosti C++ je bila lakoa njegovog upotrebljavanja za C
programere:
1. C programer C++ moe koristiti kao i obian jezik C sa strogom provjerom tipa (strong
type checking),
2. ulazno-izlazne funkcije iz C-a (printf(), scanf()) se ukljuivanjem odgovarajuih
datoteka zaglavlja (stdio.h) mogu koristiti i u C++ programima, i
3. umjesto klasa mogue je koristiti klasine C strukture koje su proirene funkcijama.

17.3 Razlike sintakse C i C++


Iako je C i C++ sintaksa vrlo slina postoje neke razlike izmeu upotrebe istih dijelova koda u C i
C++.
Sljedee razlike proizlaze iz injenice da je C++ jezik sa strogom provjerom tipa (strong type
checking):
1. sve funkcije moraju prije upotrebe imati deklaraciju ukoliko ne postoji njihova definicija
u istoj datoteci (kasnije je ovo usvojeno i u ANSI C standardu),
2. u C++ je rije void suvina:
int f(); //u C-u ne govori nita o parametrima funkcije f, a u C++
govori da funkcija f nema parametara

97

C++ i osnove objektno orijentiranog dizajna


int f(void); //u C-u govori da funkcija nema parametara, a u C++ je to
isto kao i gornja deklaracija

3. u C++ se ne vraanje vrijednosti iz funkcije koja ima povratni tip smatra grekom, a u Cu ne,
4. u C++ pridruivanje void* pokazivau vrijednosti bilo kojeg drugog pokazivaa
zahtijeva eksplicitnu pretvorbu, a u C-u ne:
int a=10;
void *pok=&a; //u C++ greka, u C-u nije

5. inicijalizacija polja znakova string konstantom je u C++ pogrena ako je duljina polja
premala za cijeli string ukljuujui i NULL znak:
char niz[3]=C++; //u C++ greka, u C-u nije

6. umjesto poziva malloc i free koriste se pozivi new i delete,


7. strukture su u C++ proirene funkcijama i mogu se koristiti umjesto klasa
8. deklaracija varijable u C++ (bez extern) smatra se definicijom te varijable. U C-u se radi
o moguoj definiciji pri emu se pri povezivanju ako ima vie moguih definicija one
stapaju u jednu,
9. u C++ podrazumijevano povezivanje povezivanje konstante je static, a u C-u extern,
10. u C++ znakovne konstante su tipa char, a u C-u tipa int,
11. C++ programer se puno manje oslanja na pretprocesor (povezivanje datoteka, uvjetno
prevoenje, provjera greaka) od C programera. U C-u se pretprocesor koristi u istu svrhu
kao i u C++ ali i za deklaraciju simbolikih konstanti i makro funkcija koje se u C++
izbjegavaju.

17.4 Novi mehanizmi u C++


C++ uvodi neke nadogradnje i razlike u odnosu na poznate mehanizme iz C-a:
1. umetanje (inlining) i preoptereenje (overloading) funkcija,
2. prijenos argumenata kao referenci (pass-by-reference) za razliku od uobiajenog C
prenoenja kao vrijednosti (pass-by-value),
3. operatori new i delete za dinamiku alokaciju umjesto malloc i free,
4. podrka za predloke (templates) funkcija i klasa,
5. podrka za apstraktne tipove podataka preko mogunosti skrivanja informacija i
definiranja javnog suelja,
6. podrka objektno orijentiranom programiranju preko mehanizama nasljeivanja i
dinamikog vezivanja (dynamic binding).
Ovi mehanizmi istiskuju neke esto koritene mehanizme iz C-a kao definiranje makro funkcija i
simbolikih konstanti.

17.5 Nove kljune rijei u C++


C++ uvodi neke nove kljune rijei:
virtual this protected new delete

98

C++ i osnove objektno orijentiranog dizajna


try template private inline class
throw public operator friend catch

Neke od njih (try, throw, catch) su vezane uz nove mehanizme koji nemaju veze s idejom
objektno orijentiranog programiranja (obrada iznimaka) ili su zamijenile neke rijei iz C-a (new i
delete zamjenjuju malloc i free). Ipak veina novih rijei vezana je uz uvoenje pojmova
vezanih uz objektno orijentirani dizajn (klase i objekti).

17.6 C++ kao objektno orijentirani jezik


Razlike u sintaksi izmeu C i C++ nisu toliko vane koliko je vana razlika u pristupu problemu.
C++ je objektno orijentirani jezik kojeg karakteriziraju tri temeljna obiljeja:
1. upotreba klasa i objekata,
2. polimorfizam, i
3. nasljeivanje.
Enkapsulacija podataka i metoda te njihovo koritenje preko javno definiranih suelja i izvedenih
objekata kroz dinamiko povezivanje predstavljaju temelj pristupa problemu. Novi objektni
pristup spada na vii stupanj apstrakcije od istog proceduralnog C pristupa, te je bio uvjetovan
rastom sloenosti programskih zadataka i veliine koda.
C++ omoguuje veliku modularnost i ponovnu iskoristivost koda (reusability) to je kljuno kod
razvoja velikih programa na kojima radi puno programera. Iako e moda veina C programa (uz
manje zahvate) raditi i u C++, to ne znai da su oni pisani u C++. U C++ se moe nastaviti
kodirati kao i u C-u jednostavno zanemarujui ekstenzivnost koju donose nove kljune rijei
(C++ jezik sintaktiki gledano predstavlja nadogradnju (superset) na C), no u tom sluaju nema
smisla prelaziti u C++.

99

You might also like