Professional Documents
Culture Documents
C++
I
OSNOVE OBJEKTNO ORIJENTIRANOG
DIZAJNA
Predavanja
Marko Lackovi
Zagreb, 2002.
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
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.
detaljan pregled C++ jezika uz opsean pregled C sintakse. Pristup objektno orjentiranom
dizajnu.
M. A. Ellis, B. Stroustrup: The Annotated C++ Reference Manual, AddisonWesley Publishing Company, Reading, Massachusetts
C++ standard
2 Plan predavanja
Teme obraene u predavanjima:
1. osnovni elementi prog. jezika C:
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
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 se obino piu malim slovima, za razliku od imena simbolikih konstanti koja se
(obino) piu velikim slovima:
8
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
3.7 Brojevi
U C++ postoje dva osnovna tipa brojeva
1. cijeli brojevi (integers), i
2. brojevi s pominim zarezom (floating point).
10
dekadskom
int a=16;
int a=020;
int a=0x10;
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
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;
11
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
int
long
float
double
12
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
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
4 Operatori
Teme obraene u ovom dijelu:
Aritmetiki operatori
Logiki operatori
Poredbeni operatori
Bitovni operatori i operator razdvajanja
Operatori pridruivanja
Hijerarhija operatora
binarni
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.;
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;
Znaenje
logiki ili
logiki i
logika negacija
Zamjenska oznaka
x or y
x and y
not x
Znaenje
razliito
jednako
vee ili jednako
vee od
manje ili jednako
manje od
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
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
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
Blokovi naredbi
Uvjetno grananje naredba if
Uvjetni operator ? :
Naredba switch
Petlja for
Naredba while
Blok do-while
Naredba break
Naredba continue
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.
17
Ne spada u naredbe za kontrolu toka programa, ali je po znaenju vrlo slian if-else bloku
Opi oblik:
uvjet ? izraz1 : izraz2 ;
se iz petlje.
Na slici 4 prikazan je blok dijagram for petlje.
19
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 )
20
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.
Polja podataka
Definicija polja
Znakovni niz
21
pri emu indeks pristupa ind moe biti jednak konstanti, varijabli ili nekom izrazu.
polje dimenzije n+1
polje dimenzije 2(n+1)
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
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;
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.
Nadovezuje niz nastavak na niz pocetak u duljini od najvie duljina znakova. Dodaje
NULL znak na kraj niza.
Trai se prva pojava znaka znak. Ako nije pronaen vraa se NULL pokaziva.
23
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 );
Kopira sadraj niza izvornik u niz odrediste. Kopiranje se prekida nakon to je dosegnut
NULL znak (NULL znak se kopira).
Pretrauje niz niz do pojave prvog znaka iz niza znakovi. Vraa se pokaziva na taj znak
ili NULL pokaziva ako nije pronaen.
Trai u nizu niz prvi znak koji se ne pojavljuje u nizu podniz. Vraa pokaziva na taj znak
ili NULL pokaziva ako nije pronaen.
Trai prvu pojavu niza podniz u nizu niz. Vraa pokaziva na mjesto prve pojave podniza
ili NULL pokaziva ako podniz nije pronaen.
Pretrauje niz niz i trai zadnju pojavu znaka znak. Vraa pokaziva na taj znak ili NULL
pokaziva ako znak nije pronaen.
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
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
Pokaziva pok pokazuje na novostvoreni objekt tipa int koji je inicijaliziran na vrijednost 2.
25
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;
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;
26
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
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).
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
return a;
}
Pri pozivu funkcije formalni argument zamjenjuje se stvarnim argumentom, tj. stvarnom
vrijednou:
int b=3;
f(b); //b je stvarni argument funkcije
return 1;
}
Prilikom prijenosa kao pokaziva ne postoji ugraena konverzija pa tipovi argumenata moraju
tono odgovarati
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
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;
}
}
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
29
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
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
}
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
void main(){
int c=f(1);
}
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.
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
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
32
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.
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
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,
zatvaranje datoteke.
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
ofstream dat(ime_datoteke,ios::mod1|ios::mod1);
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
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
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
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);
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();
36
37
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
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
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
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
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.
40
Umetnutu funkciju je mogue definirati i izvan klase, ali je tada potrebno navesti rije inline:
klasa::inline float f(void){}
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
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;
}
42
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
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
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
Poziv destruktora moe biti automatski (izlazak iz bloka) ili eksplicitan (delete) to ovisi o
deklaraciji objekta.
Kod dinamike alokacije polja mora postojati podrazumjevani konstruktor, jer tu nema
mogunosti navoenja inicijalizacijske liste:
klasa *polje=new klasa[5];
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
44
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
}
void main(void){
klasa *obj=new klasa;
int (klasa::pokF)(int, double)=klasa::f;
cout<<obj->pokF(1,1.2);
}
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
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;
};
46
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.
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.
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
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
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
49
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};
};
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
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
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));
}
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
|=
&&
<=
&
::
->*
&=
!=
>
^
.*
->
^=
==
<
%
.
()
%=
>>
=
/
[]
/=
<<
,
*
>>=
-=
-!
-
<<=
+=
++
+
51
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);
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{
52
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);
}
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
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);
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
Naputak: vektor implementirajte kao 1 dim polje.Zadani operatori trebaju raditi i u kombinaciji
sa konstantama(pretvorba u vektor odgovarajue dimenzije)
3.
55
Naputak: Za implementaciju prikaza brojeva koristite klase. Rijeite zadatak primjenom polja
znakova (char) zbog prikaza znamenaka 10-15 (A-F).
5.
56
57
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
58
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
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.
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.
60
61
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;}
};
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
62
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.
Preko objekata klase Oprijemnik mogue je javnim pristupiti metodama klasa Oelement i
Eelement:
class Oprijemnik op;
op.setBrOUlaza(10);
op.setBrEIzlaza(15);
63
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.
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.
64
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
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
BrojOulaza
BrojOizlaza
cijena
vjKvara
public:
Oelement (int brUl, int brIz, long cj, double vj) : brOUlaza(brUl),
brOIzlaza(brIz), Element(cj, vj);
};
66
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
protected:
class Stabilizator {
double Faktor;
public:
double getFaktor(void);
};
67
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.
U gornjem pozivu se provodi ugraena konverzija float -> double, pa double -> ugraena
konverzija preko konstruktora -> objekt Oelement.
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.
68
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}
};
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).
public:
69
public:
virtual void Aktiviraj(void);
};
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.
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
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
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.
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
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
73
74
75
};
return p;
};
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.
iterator repa:
++ kretanje kroz rep (sljedei element)
-- kretanje kroz rep (prethodni element)
76
iterator stoga:
++ kretanje kroz stog (sljedei element)
-- kretanje kroz stog (prethodni element)
iterator polja:
++ kretanje kroz polje (sljedei element)
-- kretanje kroz polje (prethodni element)
77
iterator kompozicije:
++ kretanje kroz spremnik (sljedea elija)
-- kretanje kroz kompoziciju (prethodna elija)
iterator liste:
++ kretanje kroz listu (sljedei poziv)
-- kretanje kroz listu (prethodni poziv)
iterator spremnika:
++ kretanje kroz spremnik (sljedei zahtjev)
78
79
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
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
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);
Umjesto rijei class prije imena formalnog argumenta dozvoljeno je koristiti i kljunu rije
typename:
template <typename tip>
tip f(tip 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);
81
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)
Lista parametara ne smije biti prazna, a parametar predloka moe biti i izraz:
template <class t1, class t2, int brElem> class imeKlase;
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){}
83
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>;
};
84
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
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
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
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.
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.
88
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.
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
14
Iznimke
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).
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!;
90
catch(iznimkaKlase &izn){}
catch blok sada prima samo iznimke koje kao poruku alju objekt klase iznimkaKlase. Na taj
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
}
}
91
15
Pretprocesorske naredbe
#line
#undef
#define
#include
#endif
#else
#elif
#ifndef
#ifdef
#if
92
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;
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
94
16
Organizacija koda
2. deklaracije funkcija
extern int f(double, char*);
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.
96
17
C i C++
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
97
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
98
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).
99