Sunteți pe pagina 1din 44

SADRAJ

1. Uvod u programski jezik C++


1.
2.
3.
4.
5.

Programski jezik C++ ............................................................................................9


Turbo C++ 2006 ......................................................................................................9
Prvi C++ program ...............................................................................................12
Stil i forma pisanja C++ programa .................................................................15
Komentari u programu ......................................................................................16

2. Varijable i konstante
1. Uvod..........................................................................................................................19
2. Int (Cjelobrojni tip) ............................................................................................19
3. Float (Realni tip)....................................................................................................20
4. Char (Znakovni tip)............................................................................................. 24
5. Imenovane konstante i typedef deklaracija ..............................................24
6. Enum konstante, long i double tipovi podataka ....................................25
7. Kvalifikatori short, signed i signed.................................................................26
8. Cast i sizeof operatori ....................................................................................... 27
9. Aritmetiki operatori ......................................................................................... 28
10. Dodjela vrijednosti izrazima............................................................................ 30
11. Strukture i unije podataka................................................................................ 32
3. Naredbe za ispis i unos podataka
1.
2.
3.
4.

Naredbe cout i cin .............................................................................................. 37


Naredbe printf i scanf ...................................................................................... 42
Ispis i unos podataka - Dodatak..................................................................... 47
Pretvorbe tipova podataka ............................................................................. 50

4. Naredbe za grananje
1.
2.
3.
4.
5.

Uvod ........................................................................................................................53
Relacijski i logiki operatori ............................................................................53
Naredba if ...............................................................................................................55
Uvjetni operator ?.................................................................................................59
Naredba switch ....................................................................................................60

5. Programske petlje
1.
2.
3.
4.
5.
6.

Uvod..........................................................................................................................64
Petlja for ..................................................................................................................64
Petlja while .............................................................................................................69
Petlja do-while ......................................................................................................70
Naredbe break i continue .................................................................................72
Naredba goto ........................................................................................................78

6. Polja i pokazivai
1.
2.
3.
4.
5.
6.

Jedno i viedimenzionalna polja ...................................................................76


Rad sa znakovima i znakovnim poljima ......................................................82
Sortiranje polja .....................................................................................................85
Pokazivai i reference .........................................................................................88
Dinamika alokacija i realokacija memorije ...............................................92
Pokazivai na pokazivae .................................................................................96

7. Funkcije i pretprocesorske naredbe


1. Uvod..........................................................................................................................99
2. Funkcija kao blok naredbi ................................................................................99
3. Primjene funkcija ...............................................................................................101
4. Funkcije i pokazivai ........................................................................................105
5. Statike varijable funkcije ..............................................................................110
6. Funkcija main( ) .................................................................................................111
7. Rekurzije................................................................................................................113
8. Lista argumenata funkcije .............................................................................115
9. Podrazumijevani parametri funkcije ..........................................................117
10. Konstantni argumenti funkcije ....................................................................118
11. Pretprocesorske naredbe ...............................................................................118
8. Rad sa datotekama
1.
2.
3.
4.
5.

Uvod ...........................................................................................................................
Datoteke i C++ ........................................................................................................
Naredbe fscanf, fprintf... ......................................................................................
Neformatirane datoteke .......................................................................................
Zatita podataka .....................................................................................................

9. Strukture i liste
1. Uvod ...........................................................................................................................
4

2.
3.
4.
5.
6.
7.

10.

Uvod u klase

1.
2.
3.
4.
5.
6.
7.
8.
9.
11.

Uvod ............................................................................................................................
Konstrukcija klase ...................................................................................................
Preoptereenje funkcije .......................................................................................
Funkcije prijatelji .....................................................................................................
Operatorske funkcije .............................................................................................
Statiki lanovi klase ..............................................................................................
Nasljeivanje klasa .................................................................................................
Virtualne funkcije ....................................................................................................
Predloci ....................................................................................................................

Sigurnosne pretvorbe i iznimke

1.
2.
3.
4.
5.
6.
7.
8.
9.
12.

STOG realiziran poljem ........................................................................................


STOG realiziran listom ...........................................................................................
Red realiziran ciklikim poljem .........................................................................
Red realiziran listom ..............................................................................................
Sortirane i viestruko povezane liste ...............................................................
Binarno pretraivanje ............................................................................................

Uvod ............................................................................................................................
Pretvorba static_cast .............................................................................................
Pretvorba dynamic_cast ......................................................................................
Pretvorba reinterpret_cast ..................................................................................
Pretvorba const_cast .............................................................................................
Generiranje i obrada iznimki .............................................................................
Standardne iznimke ...............................................................................................
Neprihvaene iznimke ..........................................................................................
Funkcije i iznimke ..................................................................................................

Kontrolne klase

1. Uvod ...........................................................................................................................
2. Klase TButton, TRadioButton i TGroupBox .....................................................
3. Klase TCheckBox, TStatic i TGauge ....................................................................
4. Klase TSlider i TScrollBar .......................................................................................
5. Klase TListBox i TComboBox ...............................................................................
6. Klase TEdit, TEditFile i TEditSearch ....................................................................
7. Operatori new i delete ..........................................................................................
8. Fontovi i objekti ......................................................................................................
9. Rad sa porukama ...................................................................................................
10. Nadogradnja kontrolnih klasa ..........................................................................
5

13.

Dijalozi i prozori

1.
2.
3.
4.
5.
6.
7.
14.

Grafika obrada

1.
2.
3.
4.
5.
15.

Uvod ...........................................................................................................................
Ikona i kursor ..........................................................................................................
Izbornik ......................................................................................................................
Dijalog .......................................................................................................................
Bitmap .......................................................................................................................
DLL resursi....................................................................................................................

Turbo C++ 2006

1.
2.
3.
4.
5.
6.
7.
8.
9.
17.

Uvod ...........................................................................................................................
Ureivanje prozora ................................................................................................
Funkcije za crtanje ..................................................................................................
Funkcija Paint ...........................................................................................................
Ispis podataka ..........................................................................................................

Resource Workshop

1.
2.
3.
4.
5.
6.
16.

Uvod ...........................................................................................................................
Dijalozi Open i SaveAs ..........................................................................................
Dijalog ChooseColor .............................................................................................
Dijalog ChooseFont ...............................................................................................
Karakteristike prozora ...........................................................................................
Poruke prozora ........................................................................................................
Rad sa vie prozora ................................................................................................

Uvod ...........................................................................................................................
Standardne i dodatne komponente ................................................................
Win32 i sistem komponente ...............................................................................
Dijalozi i Win 3.1 komponente ...........................................................................
Kreiranje i upotreba prozora ...............................................................................
Dinamika alokacija VCL komponenti ............................................................
Konfiguracijske datoteke i Windows registar ................................................
Office integracija ....................................................................................................
Dretve i procesi .......................................................................................................

Baze podataka

1. Uvod .........................................................................................................................
2. Paradox i ODBC .......................................................................................................
6

3.
4.
5.
6.
7.

18.

Mreno programiranje

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.

19.

Biblioteke i komponente

1.
2.
3.
4.
5.
6.
20.

ADO komponente ..................................................................................................


Rad sa zapisima ........................................................................................................
Konekcije u vrijeme zahtjeva .............................................................................
Klijentski skup podataka ......................................................................................
Rave reports ................................................................................................................

Uvod ..............................................................................................................................
Internet Socket komponente ...............................................................................
Indy TCP klijent-server ............................................................................................
Indy UDP klijent-server ...........................................................................................
Indy ICMP ....................................................................................................................
Indy SMTP ....................................................................................................................
Indy FTP klijent ..........................................................................................................
Indy Telnet klijent .....................................................................................................
Indy konekcije ............................................................................................................
Windows servisi ........................................................................................................

Uvod .........................................................................................................................
Statike biblioteke .................................................................................................
Dinamike biblioteke ............................................................................................
Borland komponente ............................................................................................
COM komponente ..................................................................................................
Active Form ...............................................................................................................

Linux aplikacije

1.
2.
3.
4.
5.

Uvod ..........................................................................................................................
Kylix i C++ ................................................................................................................
CLX biblioteka ..........................................................................................................
ivotni ciklus i komunikacija ..............................................................................
Prijenos aplikacija .....................................................................................................

10
10. UVOD U KLASE

1.
Uvod ....................................................................................................
.........................
2.
Konstrukcija klase ...............................................................................
............................
3.
Preoptereenje funkcije .......................................................................
..........................
4.
Deklaracija friend ................................................................................
..........................
5. UVOD
U KLASE
Operatorske
funkcije ............................................................................
..........................
6.
Statiki lanovi klase ...........................................................................
............................
1.
Uvod ....................................................................................................................................
7.
Nasljeivanje klasa ..............................................................................
2. ..........................
Konstrukcija klase ...........................................................................................................
8.
Virtualne funkcije ................................................................................
3. ..........................
Preoptereenje funkcije ...............................................................................................
9.
Predloci ..............................................................................................
4. ...........................
Deklaracija friend ...........................................................................................................
5.

Operatorske funkcije .....................................................................................................

6.

Statiki lanovi klase .....................................................................................................

7.

Nasljeivanje klasa .........................................................................................................

8.

Virtualne funkcije ............................................................................................................

9.

Predloci .............................................................................................................................

10. Uvod u klase

10.1. Uvod

Programski jezik C++ je karakteristian po tome to programeru doputa da kreira svoj tip podatka. Tako na osnovu tipova podataka koji su ve definirani moete kreirati
i vlastiti tip podatka. U tu svrhu se koriste klase. Klase su prilino sline strukturama i unijama jer se i pomou njih definira nekakav tip podatka.
Opi oblik klase:
class <ime> {
// Deklaracija lanova klase (varijable i funkcije)
}<varijable>;

Opi oblik prikazuje slinost klasa sa strukturama i unijama podataka. U klasi ili strukturi
se pojedini lanovi mogu zatititi ili ograniiti im se pristup. Ukoliko je to potrebno onda
se taj tip podatka uglavnom predstavlja kao klasa, a u protivnom kao struktura. Obino,
strukture se koriste kada se definira podatak koji ima sve javne lanove, i ne sadri funkcije. U protivnom je rije o klasi.
U veini sluajeva funkcije lanice koje se koriste za obradu novonastalog tipa podatka
(klase) se postavljaju kao javne (public), tj. mogu se koristiti prilikom obrade bilo koje varijable (instance) novonastalog tipa. Te javne funkcije mogu koristiti i neke druge pomone
funkcije koje ne moraju nuno biti dostupne svima, pa se uglavnom postavljaju kao privatne ili zatiene (private ili protected).
Pravo pristupa

Znaenje

Public

lanovi su dostupni svima (unutar i izvan klase).

Private

lanovi su dostupni samo unutar te klase. Niti potomci te klase nemaju pravo pristupa privatnim lanovima.

Protected

lanovi su dostupni samo toj klasi i njenim potomcima.

Tablica 10.1.1. Prava pristupa lanovima klase

Sve do pojma nasljeivanja klasa koristiti emo samo prva dva pristupa (public i private).
Trei pristup (protected) moemo shvatit kao proirenje pristupa private. Koristi se ako je
rije o nasljeivanju klasa kada je potrebno definirati kojim podacima mogu pristupati
potomci neke klase.

10. Uvod u klase

10.2. Konstrukcija klase



Osim obinih varijabli i funkcija, klasa moe imate konstruktor i destruktor. Njih
moemo shvatiti kao dvije karakteristine funkcije klase koje se izvravaju prilikom kreiranja njene instance tj. prilikom njenog unitenja iz memorije. Time se programeru daje
mogunost da definira to se treba dogoditi prilikom deklaracije neke varijable (objekta)
tog tipa, ili to se treba napraviti prilikom njenog unitenja (brisanja iz memorije).
Konstruktor moe imati argumente, a njima se sluimo kada elimo odmah pri kreiranju
objekta inicijalizirati neke njegove lanove, dok kod destruktora argumenata nema. Konstruktor i destruktor klase emo detaljnije obraditi u nastavku.

Primjer 10.2.1.
#include <iostream.h>
class Objekt
{

private:
// privatni lanovi...

char znak;

int broj;

public:
// Javni lanovi...

void f();
};
void Objekt::f(){

cout << "Funkcija Objekt::f()";
}
int main()
{

Objekt Instanca;

Instanca.znak = 'A';
/* greka! privatni lanovi nisu

dostupni 7*/

Instanca.f();
// ok! "f" je javna funkcija

return 0;
}

Kreirali smo klasu Objekt koja sada predstavlja novi tip podatka. Ova klasa ima dvije pomone varijable i jednu funkciju kao svoje lanove.
Primijetite na koji nain je napisano tijelo funkcije f :

10

10. Uvod u klase

void Objekt::f()...

Ova funkcija ima prototip u klasi Objekt, te se zbog toga mora navesti da je ona vlasnitvo
te klase. To se radi na nain da se, nakon to se navede tip funkcije, navede ime pripadne
klase te znakovi ::" (operator dosega). Poslije toga se navede ime funkcije i njeni parametri (ako postoje).
Ukoliko funkcije nisu velikog sadraja njihova tijela mogue je napisati i u samoj klasi.
Tada se umjesto prototipa navedene funkcije odmah pie njeno tijelo. Tako smo klasu u
primjeru 10.2.1. mogli napisati i ovako:
class Objekt
{

private:
// privatni lanovi...

char znak;

int broj;

public:
// Javni lanovi...

void f()

{

cout << "Funkcija Objekt::f()";

}
};

Primijetimo da je ova klasa preglednija od prethodne jer tijelo funkcije f se nalazi u samoj
klasi, a ne izvan. Meutim, to ne bi bio sluaj da neka od funkcija sadri mnogo naredbi.
Tada bi se radi preglednosti u klasi naveo prototip te funkcije, a njeno tijelo bi napisali
izvan klase. Openito, programeri i koriste tu praksu da zasebno napiu definiciju klase
sa svim prototipima funkcija te to spreme u header datoteku, dok sama tijela funkcija se
spremaju u cpp datoteku.
U glavnom programu smo deklarirali Instanca kao varijablu tipa Objekt. Ta varijabla predstavlja jednu kopiju navedene klase, te sada zato moemo koristiti sve njene dostupne
lanove. Njima pristupamo na isti nain kao da pristupamo nekom lanu strukture. Prvo
navedemo ime strukture, pa onda toku (.), a nakon toga ime lana. Kod struktura, unija i
klasa toka se koristi kao operator za pristup funkciji ili varijabli koja je njen sastavni dio.
Na taj nain smo pozvali i funkciju f.
Sve ovo moe djelovati jako zbunjujue jer u C++u i strukture mogu sadravati funkcije
kao svoje lanove, pa je teko uvidjeti samu razliku izmeu strukture i klase (osim u imenu). Meutim, razlika je u podrazumijevanom pravu pristupa. lanovi klase su automatski
privatni (ako se ne navede drukije), dok su lanovi strukture javni.
lanovi klase mogu biti i funkcije tipa inline. Takva funkcija je ona ije se tijelo kopira
na mjesto poziva. Time se ubrzava njeno izvravanje, no izvrni program se povea. Nije
preporuljivo koristiti inline funkcije pri radu sa programskim petljama, niti ukoliko se u

11

10. Uvod u klase

takvoj funkciji deklariraju polja veih dimenzija. Razlog? Veliina izlaznog koda tj. izvrnog
programa.
inline void f();

Sve funkcije, lanice neke klase, ija su tijela napisana u samoj definiciji te klase su automatski inline funkcije. Ukoliko elite da to budu i ostale funkcije koje imaju samo prototip
u definiciji klase, morate ispred prototipa te funkcije napisati kljunu rije inline.

Primjer 10.2.2.
#include <iostream.h>
#include <math.h>
class Tocka
{

private:

float x, y;

public:

Tocka(float a, float b); // konstruktor

float X() {return x;}
// vraca x koordinatu tocke

float Y() {return y;}
// vraca y koordinatu tocke
};
Tocka::Tocka(float a, float b){
// tijelo konstruktora klase

x = a;

y = b;
}
float UdaljenostTocaka(Tocka A, Tocka B)
{

return pow(pow(A.X()-B.X(), 2) + pow(A.Y()-B.Y(), 2), 0.5);
}
int main()
{

Tocka A(1, 1), B(2, 2);

cout << UdaljenostTocaka(A, B) << endl;

return 0;
}

Za razliku od prethodne, ova klasa ima konstruktor. Spomenuli smo da konstruktor moemo shvatiti kao funkciju. Meutim, samo kao funkciju koja NEMA povratnu vrijednost.

12

10. Uvod u klase

Ne moete je deklarirati niti kao tipa void. Konstruktor klase uvijek ima isto ime kao i sama
klasa. Npr. za klasu Tocka deklaracija konstruktora moe biti
Tocka(float a, float b); // konstruktor klase Tocka

Jedino je vano da se funkcija zove isto kao i klasa, dok argumenti unutar nje nisu uope
bitni. Nasuprot toga, destruktor, takoer ne moe imati specifikaciju o povratnoj vrijednosti. I on ima gotovo isto ime kao i sama klasa, no nikada nema argumente. Npr.:
~Tocka();

// destruktor klase Tocka

Razlika u imenu konstruktora i destruktora je samo u prvom znaku imena. Destruktor kao
prvi znak ima tildu tj. znak ~. U naim primjerima neemo se baviti destruktorom jer nam
on nije toliko vaan kao npr. konstruktor klase.
Ukoliko klasa ima konstruktor tada se prilikom deklaracije neke varijable tog tipa moraju
navesti vrijednosti argumenata koje trai konstruktor. Tako npr. za navedenu klasu Tocka
konstruktor glasi
Tocka(float a, float b);

to znai da svaku varijablu tipa Tocka moramo deklarirati tako da unutar zagrada te nove
varijable navedemo dvije vrijednosti tipa float. Npr.:
Tocka A(1.5, 1), B(2, 2.7);

Da u klasi nismo naveli postojanje konstruktora varijable A i B smo mogli deklarirati kao i
svake druge varijable (bez koritenja zagrada). Zato? Ako programer ne navede niti jedan
konstruktor onda se generira onaj podrazumijevani. U ovom sluaju to bi bio:
Tocka(){}

Meutim, ako je programer definirao jedan ili vie drugih konstruktora onda podrazumijevani konstruktor vie ne postoji. Tada ga je potrebno dodatno navesti u definiciji klase
ukoliko elite imati i tu mogunost da instance te klase kreirate poput obinih varijabli bez
ikakvih argumenata.
U naem primjeru smo definirali samo jedan konstruktor i on prima dva argumenta koji su
realni brojevi. Drugim rijeima, podrazumijevani konstruktor sada ne postoji i moramo pri
deklaraciji svake varijable tipa Tocka unutar zagrada predati i dva realna broja.
Primjer 10.2.2. prikazuje kada je to poeljan sluaj. Klasa Tocka ima konstruktor ija dva
argumenta zapravo predstavljaju koordinate nove toke, tj. nove varijable tipa Tocka. Konstruktorom smo skratili posao jer smo odmah inicijalizirali koordinate nove toke.
Unutar klase Tocka smo deklarirali i dvije funkcije. Funkcije X i Y vraaju x tj. y koordinatu
toke, dok globalna funkcija UdaljenostTocaka vraa udaljenost dviju toaka u koordinatnom sustavu. Ova funkcija kao argumente ima podatke tipa Tocka, to je sada doputeno

13

10. Uvod u klase

jer je Tocka novodefinirani tip podatka ija se definicija nalazi prije tijela te funkcije.

Primjer 10.2.3.
#include <iostream.h>
class Jednadzba
{

private:

float X, Y;

public:

Jednadzba(float a1, float b1, float c1,

float a2, float b2, float c2);

float RjX() {return X;}

float RjY() {return Y;}
};
Jednadzba::Jednadzba(float a1, float b1, float c1,

float a2, float b2, float c2)
{

if((-a1 / b1) == (-a2 / b2))

{

cout << "NEMA RJEENJA JEDNADBE!";

return;

}
X = (c1 - b1 * ((a1 * c2 - a2 * c1) / (a1 * b2 - a2 * b1))) / a1;
Y = (a1 * c2 - a2 * c1) / (a1 * b2 - a2 * b1);
}
int main()
{

Jednadzba J(1, -1, 0, 1, 3, 2); // X Y = 0; X + 3Y = 2



}

cout << J.RjX() << endl; // 0.5


cout << J.RjY() << endl; // 0.5
return 0;

Navedena klasa je tip podatka koji u sebi sadri koeficijente dviju jednadbi sa dvije nepoznanice.
Prilikom deklaracije jednadbe tj. varijable tipa Jednadzba ti se koeficijenti predaju preko

14

10. Uvod u klase

konstruktora. Unutar njega se izraunaju rjeenja jednadbe (ukoliko ih je mogue nai),


te se funkcijama RjX i RjY ta rjeenja vrate preko povratnih vrijednosti tih funkcija.
Takoer, spomenimo da postoji poseban oblik konstruktora koji se naziva konstruktor
kopije (copy constructor). On se koristi kada vrimo inicijalizaciju novog objekta pomou
nekog ve postojeeg objekta tog tipa. Tada se vri doslovno kopiranje sadraja iz jednog
objekta u drugi. Pripadni konstruktor kopije za klasu X bi izgledao ovako:
X(X const&);

Konstruktor kopije kao argument sadri referencu na konstantan objekt. Konstanta se postavlja kako se sluajno ne bi promijenio predani objekt, a referenca zbog ubrzanja poziva.
Zbog reference nee se gubiti vrijeme na kopiranje podataka i zauzimanje dodatne memorije zbog samog argumenta konstruktora. Ovo je osnovni oblik konstruktora kopije, no
on se moe proiriti i dodatnim argumentima.
Tocka A(0, 0);
Tocka B = A;
Tocka C(B);

Ovo su najei sluajevi koritenja konstruktora kopije. U prvoj naredbi smo kreirali instancu klase Tocka. Ve u drugoj naredbi koristimo konstruktor kopije. Naime,
Tocka B = A; // deklaracija i inicijalizacija (konstruktor kopije)

Ova naredba predstavlja deklaraciju (kreiranje) i inicijalizaciju objekta. Poto je rije o kreiranju nuno se poziva konstruktor, i to u ovom sluaju konstruktor kopije iji argument e
biti objekt A. Da smo imali samo
B = A; // inicijalizacija (operator pridruivanja =)

onda je rije o pridruivanju, te bi se koristio operator =. Meutim, objekt B prethodno nije


niti postojao da bi se ovaj operator mogao direktno primijeniti. Zadnja naredba takoer
prikazuje upotrebu konstruktora kopije, i to direktno uzimajui postojei objekt kao argument konstruktora klase.

10.3. Preoptereenje funkcije



Prilikom rada sa funkcijama mogue je koristiti vie funkcija sa istim imenom.
One se tada trebaju razlikovati po drugim karakteristikama (broju i tipovima argumenata).
Tada se za takvu funkciju kae da je preoptereena (overloaded).

15

10. Uvod u klase

Primjer 10.3.1.
#include <iostream.h>
#include <string.h>
class Osoba
{

private:

char ime[20];

char prezime[20];

public:

Osoba(char* ime, char* prezime){

strcpy(this->ime, ime);

strcpy(this->prezime, prezime);

}

void UzmiPodatke(char* ime){

strcpy(ime, this->ime);

}

void UzmiPodatke(char* ime, char* prezime){

strcpy(ime, this->ime);

strcpy(prezime, this->prezime);

}
};
int main()
{

char ime[20], prezime[20];

Osoba A("Ivan", "Ivic");

A.UzmiPodatke(ime);
cout << ime << endl;

A.UzmiPodatke(ime, prezime);
cout << ime << prezime; //IvanIvic
return 0;

//Ivan

Navedeni primjer prikazuje preoptereenje funkcije UzmiPodatke. Prva deklaracije ove


funkcije ima samo jedan argument kojim se dohvaa ime osobe, dok preoptereenje tj.
drugi oblik te funkcije moe pomou pokazivaa vratiti i prezime osobe.
U prvom pozivu funkcije naveo se samo jedan parametar. Po tome je program znao da

16

10. Uvod u klase

treba pozvati prvi oblik funkcije UzmiPodatke. Stoga, glavnom programu se vratilo samo
ime osobe. Pri drugom pozivu te funkcije su se navela dva parametra. Program je naao i
taj oblik te funkcije, te glavnom programu ovaj put vratio i ime i prezime osobe. Drugim
rijeima, program je bez obzira na isto ime funkcija izvravao ba onu gdje su se predani
parametri podudarali sa traenim argumentima funkcije.
Osim preoptereenja funkcije UzmiPodatke moemo primijetiti i kljunu rije this. To je
nita drugo ve pokaziva na klasu u kojoj se nalazi. Uzmimo za primjer prvi oblik funkcije
UzmiPodatke.
void UzmiPodatke(char* ime)
{

strcpy(ime, this->ime);
}

Ova funkcija se nalazi u klasi Osoba. Ta klasa kao privatni lan ima varijablu ime, no njena
funkcija lanica UzmiPodatke ima argument koji se isto tako zove. Stoga, da se prevoditelja
ne bi zbunilo uvodimo kljuni rije this i njome u ovom sluaju strogo kaemo da se referiramo na lan klase Osoba koji se zove ime, a ne na argument funkcije koji se tako zove,
tj.:
ime
this->ime

odnosi se na argument funkcije


- odnosi se na lan klase Osoba koji se naziva ime

Primjer 10.3.2.
#include <iostream.h>
class Tocka
{

private:

float x, y;

public:

Tocka(float a, float b) {x = a; y = b;}

float X() {return x;}

float Y() {return y;}
};
class Pravac
{

private:

float k, l;

public:

17

10. Uvod u klase


Pravac(float koeficijent, float odsjecak);

Pravac(Tocka A, Tocka B);

void Jednadzba();
};
Pravac::Pravac(float koeficijent, float odsjecak){

k = koeficijent;

l = odsjecak;
}
Pravac::Pravac(Tocka A, Tocka B){

k = (B.Y() - A.Y()) / (B.X() - A.X());

l = -k * A.X() + A.Y();
}
void Pravac::Jednadzba(){

cout << "Y = " << k << "x + " << l << endl;
}
int main()
{

Tocka A(1, 1), B(2, 8);

Pravac PrviPravac(1, 4);


Pravac DrugiPravac(A, B);




}

PrviPravac.Jednadzba();
DrugiPravac.Jednadzba();
return 0;

/* koeficijent smjera i odsjeak na


osi x */
/* pravac definiran dvjema tokama
u ravnini*/
// y = 1x + 4
// y = 7x - 6

Ovo je primjer u kojem vidimo preoptereenje konstruktora. Navedeni program moe deklarirati varijable tipa Pravac u dva sluaja:
a)

Ako je poznat koeficijent smjera pravca i odsjeak na koordinatnoj osi x (prvi


oblik konstruktora klase Pravac).

b)

Ako su poznate dvije toke kojima prolazi pravac (drugi oblik konstruktora klase
Pravac).

Zbog drugog sluaja smo i kreirali klasu Tocka da bi mogli deklarirati dvije varijable koje
predstavljaju dvije toke u koordinatnom sustavu. Njene funkcije X i Y smo u drugom obliku konstruktora klase Pravac upotrijebili kako bi izraunali koeficijent smjera pravca i odsjeak na koordinatnoj osi x.

18

10. Uvod u klase

10.4. Deklaracija friend



Pojam prijatelj (friend), osim u svakodnevnom ivotu mogue je koristiti ak i u
C++u. Rije je o odnosu klase i funkcije, te klase i klase. Primjerice, mogue je deklarirati
prijateljsku funkciju unutar neke klase. Takva funkcija je zapravo obina globalna ili nelanska funkcija, ali svojstvo friend joj omoguava da koristi sve lanove klase u kojoj ima
to svojstvo. To ukljuuje i privatne i zatiene lanove te klase.

Primjer 10.4.1.
#include <iostream.h>
class Tocka
{

private:

int x, y;

friend int GetX(Tocka A);

friend int GetY(Tocka A);

public:

Tocka(int x, int y){

this->x = x;

this->y = y;

}
};
int GetX(Tocka A){

return A.x;
}
int GetY(Tocka A){

return A.y;
}
int main()
{

Tocka A(1, 10);



}

cout << "X = " << GetX(A) << endl; // 1


cout << "Y = " << GetY(A) << endl; // 10
return 0;

U privatnom dijelu klase Tocka nalaze se dvije varijable i dvije funkcije. Deklarirane varija-

19

10. Uvod u klase

ble predstavljaju koordinate toke, dok se sa naredne dvije funkcije vraaju te koordinate.
Zamislimo da su funkcije GetX i GetY deklarirane bez svojstva friend i da se njihovi prototipovi ne nalaze u definiciji klase Tocka.
U tom sluaju one bi bile obine globalne funkcije i ne bi mogle pristupiti lanovima x i
y koji se nalaze u privatnom dijelu klase Tocka. Meutim, poto se njihovi prototipovi sa
svojstvom friend nalaze u definiciji klase, one e bez obzira to nisu njene lanice imati
pristup svim njenim lanovima.
U naem primjeru prototipovi funkcija GetX i GetY su navedeni u privatnom dijelu klase
Tocka, no deklaracija friend moe se nalaziti bilo gdje u klasi. Takoer, mogli smo i tijela tih
funkcija napisati unutar klase, no svejedno treba imati na umu da one ne mijenjanju svoju
izvornu definiciju tj. da i dalje ostaju globalne ili funkcije lanice neke druge klase.
Primjer 10.4.2.
class Tocka{

friend class Pravac;

int x, y;

public:

Tocka(int a, int b) : x(a), y(b){}
};
class Pravac{

public:

Tocka A1, B1;

Pravac(Tocka A, Tocka B) : A1(A), B1(B){}

int Kvadrant(Tocka A){

if(A.x > 0 & A.y > 0) return 1;

if(A.x < 0 & A.y > 0) return 2;

if(A.x < 0 & A.y < 0) return 3;

if(A.x > 0 & A.y < 0) return 4;

}
};

Deklaracija friend se moe odnositi i na klasu. Sada vidimo kako klasa Pravac ima pristup
privatnim lanovima klase Tocka. Svejedno, preporuljivo je ne koristiti deklaraciju friend
jer se njome omoguuje lagani uvid u strukture podataka te time ugroava jedno od temeljnih naela rada s klasama skrivanje podataka.

20

10. Uvod u klase

10.5. Operatorske funkcije



Kada se radi sa klasama tj. kada definirate svoj korisniki tip podatka mogue
je za njega osim funkcija i varijabli definirati i operatore. Njima omoguavate i definirate
neke osnovne aritmetike ili druge operacije sa tim podatkom. Pomou operatora moemo definirati komunikaciju izmeu vae klase i ostalih tipova podataka, a operatore
uvodimo i definiramo pomou operatorskih funkcija.

Primjer 10.5.1.
#include <iostream.h>
class Kompleksni
{

public:

double re, im;

Kompleksni(){} // podrazumijevani konstruktor

Kompleksni(double re, double im);

Kompleksni operator +(double re); // zbrajanje

Kompleksni operator -(double re); // oduzimanje

Kompleksni operator =(double re); // pridruivanje
};
Kompleksni::Kompleksni(double re, double im)
{

this->re = re;

this->im = im;
}
Kompleksni Kompleksni::operator +(double re)
{

this->re += re;

return *this;
}
Kompleksni Kompleksni::operator -(double re)
{

this->re -= re;

return *this;
}
Kompleksni Kompleksni::operator =(double re)
{

this->re = re;

21

10. Uvod u klase

this->im = 0;
return *this;

int main()
{

Kompleksni A(2.5, 6), B(4, 1.3), C;
A = A + 4.5; // A = A.operator +(4.5);

B = B - 2.4; // B = B.operator -(2.4);

C = 10.23;
// C.operator(10.23);
cout << "A.re = " << A.re << "\tA.im = " << A.im << endl;

cout << "B.re = " << B.re << "\tB.im = " << B.im << endl;

cout << "C.re = " << C.re << "\tC.im = " << C.im << endl;

return 0;
}

Najlake je definirati operatore poput operatora pridruivanja (=), no i binarni operatori


poput + (plus) i (minus) mogu se definirati vrlo jednostavno. U konkretnom sluaju, definirali smo spomenute operatore da bi mogli kompleksnom broju zbrojiti ili oduzeti realni
dio. Npr.:
Kompleksni Kompleksni::operator +(double re)
{

this->re += re;

return *this;
}

U ovoj operatorskoj funkciji vidimo kako je definirano zbrajanje sa realnim brojem. Zbroj
realnog broja i kompleksnog je kompleksni broj, te je stoga povratna vrijednost operatorske funkcije podatak tipa Kompleksni. Nakon kljune rijei operator, naveli smo zagrade u
kojima definiramo tip podatka i varijablu koju elimo dodati kompleksnom broju, a u tijelu
funkcije smo definirali to zbrajanje.
Komentirajmo zadnju naredbu u ovoj operatorskoj funkciji:
return *this;

Prethodno smo ve objasnili to predstavlja kljuna rije this. To je pokaziva na klasu u


kojoj se nalazi, no kako mi moramo vratiti konkretnu vrijednost koja se nalazi na toj adresi
(neki kompleksni broj) koristimo *this. Sada e funkcija gornjom naredbom vratiti ba neki
kompleksni broj, a ne adresu na kojoj se on nalazi.

22

10. Uvod u klase

Zato sada naredbom


A = A + 4.5;

// A = A.operator +(4.5);

program zna da to zapravo znai poveanje realnog dijela kompleksnog broja za vrijednost 4.5. Meutim, gornje dvije operatorske funkcije rade sa jednom pretpostavkom, a to
je da se pridruena vrijednost nalazi sa desne strane operatora +, dok se instanca treba
nalaziti na lijevoj strani. Naime,
A = A + 4.5;
i
A = 4.5 + A;

// ok
// greka!

nisu uope iste stvari. U C++u ova dva zbrajanja se mogu definirati kao sasvim razliita.
Stoga, bolje je operatorske funkcije pisati tako da se odmah pomou argumenata definira
i mjesto za pojedini tip podatka. Tonije, da se definira koji tip podatka treba ii prije navoenja operatora, a koji poslije.

Primjer 10.5.2.
#include <iostream.h>
class Kompleksni
{

public:

double re, im;

Kompleksni(){}
// podrazumijevani konstruktor

Kompleksni(double re, double im);
};
Kompleksni::Kompleksni(double re, double im)
{

this->re = re;

this->im = im;
}
//Kompleksni + Kompleksni
Kompleksni operator +(Kompleksni A, Kompleksni B){

return Kompleksni(A.re + B.re, A.im + B.im);
}
//Kompleksni + double
Kompleksni operator +(Kompleksni Z, double re){

return Kompleksni(Z.re + re, Z.im);
}

23

10. Uvod u klase

//double + Kompleksni
Kompleksni operator +(double re, Kompleksni Z){

return Z + re; // operator +(Kompleksni, double)...
}
int main()
{

Kompleksni A(2, 6), B(1.5, 2.5), C;

A = A + 1.5;
C = A + 2.5 + B;

// Kompleksni + double
// Kompleksni + double + Kompleksni

cout << "A.re = " << A.re << "\tA.im = " << A.im << endl;
cout << "B.re = " << B.re << "\tB.im = " << B.im << endl;
cout << "C.re = "<< C.re << "\tC.im = " << C.im << endl;
return 0;

Ispis programa:
A.re = 3.5
B.re = 1.5
C.re = 7.5

A.im = 6
B.im = 2.5
C.im = 8.5

Kada elimo definirati koji tip podatka treba biti prije i koji poslije navoenja operatora
moramo koristiti globalne operatorske funkcije. One moraju biti globalne jer operatorske
funkcije lanice neke klase imaju samo jedan argument, dok se za drugi podrazumijeva da
je instanca klase u kojoj se nalazi.
Ve smo prikazali zato je to mana, pa smo zato u ovom sluaju koristili globalne operatorske funkcije. Pogledajmo za primjer jednu od njih:
//Kompleksni + double
Kompleksni operator +(Kompleksni Z, double re)
{

return Kompleksni(Z.re + re, Z.im);
}

Ova operatorska funkcija ima dva argumenta. Tonije ona definira zbrajanje u sluaju kada
se sa lijeve strane operatora + nalazi podatak tipa Kompleksni, a sa desne strane podatak
tipa double. Isto smo napravili i u sljedeoj funkciji prototipa

24

10. Uvod u klase

Kompleksni operator +(double re, Kompleksni Z);

gdje smo definirali zbrajanje u sluaju kada se sa lijeve strane operatora + nalazi realan
broj, a sa desne strane podatak tipa Kompleksni. Ovim dvjema funkcijama smo i omoguili
operacije koje smo koristili u programu:
A = A + 1;
C = A + 1 + B;

// Kompleksni + realni
// Kompleksni + realni + Kompleksni

Za zadnju operaciju smo koristili i operatorsku funkciju koja definira zbrajanje dvaju kompleksnih brojeva jer ono to je sa lijeve strane jednakosti (podatak tipa Kompleksni) mora
biti isto to i ono sa desne strane jednakost (podatak tipa Kompleksni).
return Kompleksni(Z.re + re, Z.im);

Za povratnu vrijednost smo u jednoj od operatorskih funkcija koristili privremeni objekt.


To je objekt koji postoji samo za vrijeme izvravanja odreenog programskog koda, a nakon toga se unitava. U ovom sluaju on samo postoji u trenutku kada operatorska funkcija treba vratiti povratnu vrijednost.
Takoer, osim binarnih aritmetikih operatora moemo definirati i one unarne, operatore
pretvorbe i operatore za definiranje ulaznog i izlaznog toka podataka.

Primjer 10.5.3.
#include <iostream.h>
#include <math.h>
class Kompleksni
{

public:

double re, im;

Kompleksni(){}
// podrazumijevani konstruktor

Kompleksni(double re, double im);

Kompleksni& operator ++();
// prefiks ++

Kompleksni operator ++(int); // postiks ++

operator double(); // operator pretvorbe u double
};
Kompleksni::Kompleksni(double re, double im)
{

this->re = re;

this->im = im;
}

25

10. Uvod u klase

// prefiks operator ++
Kompleksni& Kompleksni::operator ++()
{

++this->re;

++this->im;

return *this;
}
// postfiks operator ++
Kompleksni Kompleksni::operator ++(int)
{

Kompleksni Pom = *this;

++(*this);

return Pom;
}// operator pretvorbe u double
Kompleksni::operator double()
{

// vraa modul kompleksnog broja

return pow(pow(this->re, 2) + pow(this->im, 2), 0.5);
}
// operator za izlazni tok <<
ostream& operator <<(ostream& izlaz, Kompleksni Z)
{

izlaz << Z.re << " + " << Z.im << "j";

return izlaz;
}
int main()
{

Kompleksni A(1, 1);




}

cout << (double)A << endl;


cout << A++ << endl;
cout << ++A << endl;

return 0;

// 1.41421
// 1 + 1j
// 3 + 3j

Programski jezik C++ dozvoljava da se posebno definiraju postfiks i prefiks operatori ++, a
razlika izmeu prototipa ovih operatorskih funkcija je samo u tome to postfiksni operator
++ ima dodatni argument. Takoer, prefiks operator vraa referencu.
Kompleksni& operator ++();

26

// prefiks ++

10. Uvod u klase

Kompleksni operator ++(int); // postiks ++

Uveli smo i operator pretvorbe double. Tonije, njime smo omoguili upotrebu cast operatora double nad podatkom tipa Kompleksni, a kao rezultat te pretvorbe e se vratiti modul
kompleksnog broja.
Koristili smo i operator <<. Ovo je operator izlaznog toka koji se koristi kada elite ispisati
neke podatke. Poto je Kompleksni novi tip podatka dodatno smo preopteretili operatorsku funkciju << te omoguili i definirali ispis za podatak tipa Kompleksni. Osim za ispis,
mogli smo zasebno definirati i operatorsku funkciju >> za uitavanje novog podatka tipa
Kompleksni, a ona bi izgledala ovako:
// operator za ulazni tok >>
istream& operator >>(istream& ulaz, Kompleksni& Z)
{

ulaz >> Z.re >> Z.im;

return ulaz;
}

Ova operatorska funkcija bi omoguilo uitavanje kompleksnog broja sa tipkovnice


naredbama:
Kompleksni A;
cin >> A;

Jedan operator se moe koristiti u neogranienom broju sluajeva. Zato je svako definiranje operatora nita drugo ve preoptereenje operatorske funkcije. Ukoliko se operator
slui i privatnim lanovima klase onda se vrlo esto takve operatorske funkcije deklariraju
i kao tipa friend unutar te klase.

10.6. Statiki lanovi klase



Kreiranjem klase definirate novi tip podatka, a lanovi klase definiraju od ega
se taj tip podatka sastoji i to on koristi. Svi objekti tog tipa (instance) imaju svoju kopiju
tih podataka i spremaju ih u svoj zasebni memorijski prostor. Meutim, mogue je u klasi
definirati i podatke koji se meusobno dijele izmeu svih instanci. To su statiki lanovi
klase.

27

10. Uvod u klase

Primjer 10.6.1.
#include <iostream.h>
class A
{

public:

static int n;
};
int A::n = 0; // inicijalizacija statikog lana
int main()
{

A obj1, obj2;






}

cout << obj1.n << << obj2.n << endl; // 0 0


obj1.n = 1;
cout << obj1.n << << obj2.n << endl; // 1 1
obj1.n = 2;
cout << obj1.n << << obj2.n << endl; // 2 2
return 0;

Kada se koriste statiki lanovi u klasi potrebno ih je prije poetka programa obavezno
inicijalizirati. Nadasve, neete moi ni pokrenuti program ukoliko to niste napravili.
Promotrimo glavni program. Prvo smo ispisali
cout << obj1.n << << obj2.n << endl; // 0 0

Poto je rije o statikom lanu klase koji je u poetku inicijaliziran na vrijednost 0, sve instance klase A e vrijednost tog lana proitati kao 0. U drugoj naredbi smo preko instance
obj1 promijenili vrijednost statikog lana u vrijednost 1, ali se pri ispisu ispisuje 1 1, to
znai da je i druga instanca obj2 uvidjela promjenu jer koriste dijeljeni lan. Isti sluaj se
dogaa i u zadnjem ispisu gdje smo ovaj put preko instance obj2 promijenili vrijednost
statikog lana, pa se ispisuje 2 2.
Statiki lanovi klase mogu posluiti i u sluaju kada elite brojati ili numerirati instance,
to pokazuje i sljedei primjer.

28

10. Uvod u klase

Primjer 10.6.2.
#include <iostream.h>
class A
{

public:

static int kol;

int rb;

A(){ rb = ++kol; }
};
int A::kol = 0;
int main()
{

A obj1, obj2, objX[5];

cout << "Kreirano je " << A::kol << " instanci tipa A\n";


// ispis rednih brojeva instanci

cout << obj1.rb << obj2.rb;

for(int i = 0; i < 5; i++)

cout << objX[i].rb;

return 0;
}

Ispis programa:
Kreirano je 7 instanci tipa A
1234567

Osim statikih varijabli klase, moemo koristiti i statike funkcije. To su funkcije koje rade
samo sa statikim lanovima. Pomou njih se moe itati i mijenjati vrijednost statikog
lana neke klase bez potrebe kreiranja njene instance.

29

10. Uvod u klase

Primjer 10.6.3.
#include <iostream.h>
class A
{

private:

static

public:

static


}

static


}
};
int A::N = 0;

int N;
int VratiN(){
return N;
void PostaviN(int x){
N = x;

int main()
{

cout << A::VratiN();

A::PostaviN(5);

cout << A::VratiN();

return 0;
}

// 0
// 5

Statika varijabla N je sada postavljena kao privatna. Da je postavljena kao javna mogli bi
joj pristupiti naredbom
A::N

te ju proitati i izmijeniti po volji. Meutim, poto ona zbog prava pristupa nije dostupna
upotrijebili smo statike funkcije kojima moemo dobiti identian rezultat. Naime, statika funkcija VratiN vraa vrijednost statikog lana N, dok statika funkcija PostaviN mijenja
vrijednost tog statikog lana.
Ono to je ovdje prednost pri koritenju statikih funkcija jest da nam uope nije potrebna
niti jedna instanca klase A da bi proitali i izmijenili statiki lan.

30

10. Uvod u klase

10.7. Nasljeivanje klasa



Jedno od najvanijih svojstava jezika C++ je nasljeivanje. Na osnovu tog svojstva je jednostavno moi pisati ak i sloene GUI aplikacije. Nasljeivanjem se smanjuje
koliina programskog koda, pojednostavljuje se definiranje sloenih objekata i onih koji
imaju neka zajednika svojstva. Vrlo korisni primjeri se mogu nai ba u pisanju Windows
aplikacija koritenjem Borlandove OWL ili Microsoft MFC biblioteke gdje se prozori piu
nasljeivanjem od klase praznog prozora itd..
Nasljeivanje je postupak kada se kreira zasebna klasa koja od jedne ili vie drugih klasa
nasljeuje lanove. Istovremeno, ta nova klasa moe imati i neke svoje vlastite lanove,
dok one naslijeene moe i preopteretiti (ako je rije o funkcijama). Klasa od koje se vri
nasljeivanje se uglavnom naziva klasa roditelj, dok klase koje nastaju nasljeivanjem se
nazivaju djeca, izvedenice ili derivacije.

Primjer 10.7.1.
#include <iostream.h>
class A
{

private:

int privatnaA;

public:

int javnaA;

protected:

int zasticenaA;
};
class B : public A
{

public:

int javnaB;

void ProvjeraPristupa()

{


privatnaA = javnaB; // privatnaA nije dostupna!

javnaA = javnaB;
// ok!

zasticenaA = javnaB; // ok!

}
};
int main()

31

10. Uvod u klase

B obj;

// provjera pristupa
obj.javnaB;
// ok! javnaB je lan klase B

// pristup naslijeenim lanovima


obj.privatnaA;
// nije dostupno!
obj.javnaA;
// ok!
obj.zasticenaA; // nije dostupno van klase B!
return 0;

U ovisnosti o pravima pristupa, nije mogue naslijediti sve lanove klase roditelja. Tonije,
nije mogue naslijediti samo privatne lanove. Meutim, mogue je da e derivacija klase
roditelja takoer postati klasa od koje se nasljeuje (klasa roditelj), te se zbog toga nivoi
nasljeivanja mogu detaljno definirati:
class B : public A

Klasa B sada koristi javno nasljeivanje. To je najei oblik koji se koristi i njime definiramo
da e klasa B naslijediti lanove klase A i to na nain da e naslijeeni lanovi imati ista
prava pristupa kao i u klasi A. Osim javnog, mogue je izvriti privatno i zatieno nasljeivanje.
Nasljeivanje

Znaenje

Public

Javni lanovi klase roditelja postaju javni lanovi izvedene klase. Zatieni lanovi klase roditelja postaju zatieni lanovi izvedene klase.
Privatni lanovi klase roditelja nisu dostupni izvedenoj klasi.

Private

Javni i zatieni lanovi klase roditelja postaju privatni lanovi izvedene


klase. Privatni lanovi klase roditelja nisu dostupni izvedenoj klasi.

Protected

Javni lanovi klase roditelja postaju zatieni lanovi izvedene klase.


Zatieni lanovi klase roditelja postaju privatni lanovi izvedene klase.
Privatni lanovi klase roditelja nisu dostupni izvedenoj klasi.

Tablica 10.7.1. Metode nasljeivanja

Pogledajmo funkciju ProvjeraPristupa koja se nalazi unutar klase B. Prvom naredbom smo

32

10. Uvod u klase

pokuali pristupiti privatnom lanu klase A, no to e biti greka jer privatni lanovi klase
roditelja nisu dostupni u izvedenoj klasi. Drugom naredbom smo uspjeno pristupili javnom lanu klase A jer se moe on moe naslijediti. Takoer i trea naredba
zasticenaA = javnaB;

e biti izvrena jer zatieni lanovi klase roditelja su dostupni izvedenoj klasi. Meutim,
zatieni lanovi klase roditelja nisu dostupni van te klase, to se vidi u glavnoj funkciji
main gdje preko instance klase B nismo uspjeli pristupiti lanu zasticenaA. Ovo je i smisao
zatienog lana.
Nasljeivanje od vie klasa je takoer vrlo jednostavno za izvesti:

Primjer 10.7.2.
#include <iostream.h>
class A
{

public:

A(){ cout << "A "; }
};
class B
{

public:

B(){ cout << "B "; }
};
class C: public A, public B
{

public:

C() : A(), B(){ cout << "C ";
};
int main()
{

C obj;

return 0;
}

Ispis programa:

A B C

33

10. Uvod u klase

Osim primjera viestrukog nasljeivanja, ovim primjerom smo prikazali sluaj kada se pri
tome koriste i konstruktori klasa roditelja. Prvo se izvravaju konstruktori naslijeenih klasa, i to redom od lijeva na desno, a tek nakon toga konstruktor izvedene klase. Ukoliko
izvedena klasa ima podrazumijevani konstruktor onda nije nuno potrebno koristiti konstruktore izvedenih klasa.
Bez svojstva nasljeivanja bilo bi gotovo nezamislivo pisati Windows aplikacije. Za svaki
program bi nam bilo potrebno desetak datoteka programskog koda, dok se na ovaj nain
jednostavno nadogradi postojea klasa u kojoj se nalaze osnovni dijelovi koji su potrebni
za aplikaciju.

10.8. Virtualne funkcije



Objekti koji su nastali nasljeivanjem uvijek se mogu predstaviti i klasom roditelja tj. pretvorbom na vie. Primjerice, recimo da imamo klase Pas i Maka. One bi se mogle
predstaviti jednom klasom, a nju bi mogli nazvati Zivotinja, to naravno podrazumijeva i
da su klase Pas i Maka derivacije te klase. Ovo je korisna stvar ukoliko piete funkcije koje
kao argument trebaju imati derivaciju neke klase, ali niste u potpunosti sigurni o kojoj je
derivaciji rije.
Virtualne funkcije ete upotrebljavati u sluajevima kada pokaziva klase roditelja adresirate na njen potomak. Tada, u normalnom sluaju pristup funkcijskim lanovima bi se
odnosio na lanove klase roditelja. No, ukoliko je u njemu neki od funkcijskih lanova deklariran kao virtualan onda e se pristup odnositi na taj isti funkcijski lan koji se nalazi u
derivaciji klase na koju je adresiran roditelj. Npr.:

Primjer 10.8.1.
#include <iostream.h>
class Zivotinja
{

public:

virtual void Vrsta(){}
};
class Pas : public Zivotinja
{

34

10. Uvod u klase


public:

void Vrsta(){

cout << "Pas\n";

}
};
class Macka : public Zivotinja
{

public:

void Vrsta(){

cout << "Macka\n";

}
};
int main()
{

Pas Rex;

Macka Mac;

Zivotinja *Ziv;





}

Ziv = &Rex;
Ziv->Vrsta(); // Pas
Ziv = &Mac;
Ziv->Vrsta(); // Macka
return 0;

Kljuna operacija je adresiranje pokazivaa Ziv. Time se zapravo stvara veza izmeu klase
roditelja i potomka. Kako u sve tri klase postoji ista funkcija (Vrsta) pitanje je koja e se
izvriti. Kljunom rijei virtual smo funkciju Zivotinja :: Vrsta definirali kao virtualnu. Zbog
toga e se program pokuati adresirati na tu istu funkciju koja se nalazi u derivacijama tj. u
klasi Pas ili Macka, a nee koristiti onu iz klase Zivotinja.
Adresiranjem navedenog pokazivaa zapravo smo odredili tip podatka (potomak) koji
sadri svoju inaicu funkcije Vrsta. Kada je poznat potomak automatski se zna koja e se
funkcija Vrsta izvriti. Npr., Rex je varijabla tipa Pas. Kako je pokaziva Ziv adresiran na varijablu Rex to znai da e se izvriti tijelo funkcije Vrsta koje se nalazi unutar klase Pas, jer Rex
je varijabla tipa Pas. Ukoliko kljuna rije virtual ne bi bila navedena program ne bi nita
ispisao jer bi se pozvala funkcija Vrsta iz klase Zivotinja, a njeno tijelo je prazno.
Kako ova virtualna funkcija ima tijelo (iako je prazno) mogue je kreirati zaseban objekt
(varijablu) tipa Zivotinja. Meutim, tijelo virtualne funkcije ne mora nuno postojati. U tom
sluaju ona moe biti ista virtualna funkcija.

35

10. Uvod u klase

virtual void ispis() = 0;

Ovo je primjer deklaracije iste virtualne funkcije. Klasa u kojoj se nalazi ovakva funkcija se
smatra apstraktnom (zamiljenom), te nije mogue izravno kreirati objekt takve zamiljene klase, ve samo pokaziva na njega.
Potrebno je spomenuti da u klasi jedino konstruktor ne moe biti virtualan, dok destruktor
to moe biti. Nadasve, nekada je to i nuno. Npr.:

Primjer 10.8.2.
class Bazna
{
public:
virtual ~Bazna(){
cout << "Destruktor bazne klase...\n";
}
};
class Derivacija : public Bazna
{

private:

int* polje;

public:

Derivacija(int n){

polje = new int[n];

}

~Derivacija(){

delete[] polje;

cout << "Polje je dealocirano! (destruktor

derivacije...)\n";

}
};

Derivacija nasljeuje baznu klasu. Meutim, derivacija klase pri svom unitenju mora dealocirati zauzetu memoriju i zato je nuno da se destruktor derivacije izvri. No, zbog eventualne pretvorbe na nie mogua je ovakva situacija:
Bazna* X = new Derivacija(10);
delete X;

36

10. Uvod u klase

U ovom sluaju po definiciji (deklaraciji) X je pokaziva koji pokazuje na objekt bazne klase. No, on po inicijalizaciji (pretvorbi na nie) zapravo pokazuje na objekt derivacije. Meutim, zbog svoje deklaracije, prilikom oslobaanja memorije poziva se samo destruktor
bazne klase.
Kada bi se to sada dogodilo imali bi memory leak tj. zauzeta memorija u derivaciji klase
ne bi bila dealocirana. Zbog toga, destruktor bazne klase moram deklarirati kao virtualan.
Ako je destruktor bazne klase virtualan prevoditelj e shvatiti da je X zapravo derivacija i
prvo e pokrenuti destruktor derivirane klase, pa tek onda destruktor bazne klase.

10.9. Predloci

Kada se deklarira funkcija uvijek je potrebno navesti sve tipove podataka i argumente koje ona koristi. Takva funkcija se moe koristiti samo ako prima argumente prethodno deklariranog tipa. Tako npr. ukoliko deklarirate funkciju int zbroj(int a, int b) znate
da ona moe posluiti samo ukoliko su njeni argumenti cijeli brojevi. Ukoliko biste htjeli
da funkcija vraa zbroj dva realna broja morali biste napisati novu funkciju koja za argumente ima realne brojeve.
Meutim, kada bi to radili za svaki postojei tip podatka onda bi to bio naporan posao.
Umjesto toga, mogue je deklarirati familiju srodnih funkcija koje rade isti posao neovisno
o tipovima podataka koje koriste. Kada deklariramo familiju takvih funkcija onda koristimo deklaraciju template.
Sintaksa:
template <template-argument-list> Deklaracija;

Template-argument-list je dio u kojemu se navodi koliko razliitih tipova podataka (klasa)


ete koristiti. Ukoliko e vaa funkcija koristiti samo jedan tip podatka onda se deklarira
samo jedna klasa, dok se za svaki drugi tip podatka deklarira po jo jedna klasa. Tako npr.
ukoliko e vaa funkcija zbrojiti i vratiti sumu realnih brojeva onda ete deklarirati samo
jednu klasu jer se koristi samo jedan tip podatka (realni brojevi).
Deklaracija je standardni dio u kojemu se deklarira funkcija (povratni tip, ime i argumenti).
Osim kod funkcija, deklaraciju template je mogue koristiti i kod klasa. U tom sluaju se u
dijelu Deklaracija navodi deklaracija klase, a ne funkcije.

37

10. Uvod u klase

Primjer 10.9.1.
#include <iostream.h>
template <class Tip1>
Tip1 zbroj(Tip1 a, Tip1 b)
{

return (a + b);
}
int main ()
{

cout << zbroj(2, 4) << endl; // ... int zbroj(int a, int b)

cout << zbroj(3.14, 6.33) << endl;

// ... float zbroj(float a, float b)

cout << zbroj('A', char(3));

// ... char zbroj(char a, char b)

return 0;
}

Ispis programa:
6
9.47
D

U glavnom programu smo tri puta pozvali funkciju zbroj. Prvi put njeni argumenti su bili
cijeli brojevi, drugi put su to bili realni brojevi, a potom znakovi. Karakteristika ovih tipova
podataka jest da je za njih definirana operacija zbrajanja (+). Da su kao argumenti funkcije
postavljeni tipovi podataka za koje nije definiran operator + funkcija zbroj ne bi vratila
toan rezultat, ili se na nekim prevoditeljima program uope ne bi pokrenuo.
Deklaracija funkcije zbroj koja kao rezultat vraa
podatak tipa Tip1, dok su joj argumenti dva podatka tipa
Tip1.
template

<classTip1>

Tip1 zbroj (Tip1 a, Tip1 b


Funkcija zbroj koristi samo jedan promjenjivi tip
podatka (Tip1). On se koristi za deklaraciju argumenata i
kao povratna vrijednost funkcije.

38

10. Uvod u klase

Iz gore navedenog se vidi da funkcija zbroj se moe koristiti samo kada se zbrajaju podaci
istog tipa (Tip1). Tip1 moe biti svaki tip podataka za koji postoji definiran operator +. U
prvom sluaju Tip1 je postao int, u drugom sluaju float, a potom char.

Primjer 10.9.2.
#include <iostream.h>
class Kompleksni{

public:

double re, im;

Kompleksni(){}

Kompleksni(double re){

this->re = re;

im = 0;

}

Kompleksni(double re, double im){

this->re = re;

this->im = im;

}

void operator =(double r){

re = r;

im = 0;

}
};
Kompleksni operator +(Kompleksni A, Kompleksni B){

return Kompleksni(A.re + B.re, A.im + B.im);
}
ostream& operator <<(ostream& izlaz, Kompleksni Z){

cout << Z.re << " + " << Z.im << "j";

return izlaz;
}
template <class T1>
T1 Suma(T1 *polje, int n)
{

T1 s;

s = 0;
if(n <= 0) return 0;

39

10. Uvod u klase


for(int i = 0; i < n; i++)

s = s + polje[i];

return s;
}
int main()
{

int polje1[3] = {1, 2, 4};

float polje2[3] = {1.5, 2.5, 3.5};

Kompleksni polje3[3] =
{

Kompleksni(1, 1),

Kompleksni(4.2, 5),

Kompleksni(3, 4.2)

};

cout << Suma(&polje1[0], 3) << endl; // 7

cout << Suma(&polje2[0], 3) << endl; // 7.5

cout << Suma(&polje3[0], 3) << endl; // 8.2 + 10.2j

return 0;
}

Napisani predloak funkcije Suma predstavlja funkciju koja kao argument prima odreeno polje podataka i njihov broj elemenata, a vraa sumu svih elemenata tog polja. U glavnom programu smo pri pozovu te funkcije prvo predali cjelobrojno, pa zatim realno polje
podataka. To su ve definirani tipovi podataka i funkcija je bez problema uspjela izraunati
i vratiti sumu tih polja.
No, u zadnjem pozivu te funkcije predano je korisniki definirano polje podataka tipa
Kompleksni. Poto je rije o korisniki definiranom tipu podatka sa kojim radi predloak
funkcije treba paziti da ta klasa zadovoljava sve to predloak funkcije treba da bi uspjeno obavio posao. Predloak funkcije treba sljedee:
a)

Pomonu varijablu u koju e spremiti sumu elemenata polja.

Zbog ove potrebe morali smo u klasi Kompleksni deklarirati podrazumijevajui konstruktor. Inae bi naredba T1 s bila prijavljena kao greka.
b)

Inicijalizirati sumu na vrijednost 0.

Da bi se ovo pridruivanje uspjeno obavilo u klasi Kompleksni smo morali deklarirati operator pridruivanja = .
c)

Znati kako se zbrajaju predani tipovi podataka.

Predloak funkcije u ovom sluaju treba zbrajati kompleksne brojeve, a da bi to bilo mogue u klasi Kompleksni smo morali izvriti preoptereenje operatorske funkcije +. Da ovaj

40

10. Uvod u klase

operator nije definiran za sluaj zbrajanja kompleksnih brojeva predloak funkcije bi javio
greku da ne zna kako zbrojiti kompleksne brojeve.

Primjer 10.9.3.

#include <iostream.h>
template <class T1, class T2>
double Suma(T1 a, T2 b){

return a + b;
}
double Suma(double a, double b){

cout << "Preoptereenje predloka! ";

return a + b;
}
int main()
{

cout << Suma(2.5, 4.3); // Preoptereenje predloka! 6.8

return 0;
}

Predloke funkcija je mogue i preopteretiti kao to je prikazano u ovom primjeru. Bez


obzira na to to e tokom izvoenja sam predloak definirati oblik funkcije za zbrajanje
dvaju podataka tipa double, ukoliko postoji preoptereenje koje definira tono taj sluaj
onda e se izvriti ta preoptereena funkcija.
Predloci funkcija e tek u vrijeme izvoenja doznati tipove podataka sa kojima rade, a
za to se brine prevoditelj. Na programeru je samo da pazi kakve tipove podataka koristi
u predlocima funkcija, i da bude siguran da ti tipovi podataka zadovoljavaju sve to je
potrebno da se funkcija uspjeno izvri, kao to je prikazano i u gornjem primjeru.
Osim predloaka funkcija mogu se kreirati i predloci klasa. Njih koristimo kada elimo
kreirati klasu koja kao svoje lanove moe imati tipove podataka koji su poznati tek u
vrijeme izvoenja.

41

10. Uvod u klase

Primjer 10.9.4.
template <class T>
class STOG
{

public:

T* vrh;

int DodajElement(T element);

int SkiniElement(T &element);
};
template <class T> int STOG<T>::DodajElement(T element){
// ...
}
template <class T> int STOG<T>::SkiniElement(T &element){
// ...
}

Primjerice, ovaj predloak klase predstavlja strukturu podataka STOG. Da je ovo obina
klasa onda bi se odmah znalo koji tip podatka se nalazi na STOG-u, no to e ovako biti
samo poznato u vrijeme izvoenja. Npr.:
Stog <int> MojStog; // stog s cijelim brojevima
Stog <double> MojStog;
// stog s realnim brojevima
Stog <Kompleksni> MojStog; // stog s kompleksnim brojevima

Kreiranje instance ovakve klase se vri tako da se nakon imena predloka navedu znakovi
< (manje) i > (vee) unutar kojih se navede tip podataka koji e se koristiti u generiranoj
klasi. Tek nakon toga se navodi ime instance.

Zadatak 1: Napii predloak klase koja predstavlja polje elemenata proizvoljnog tipa. Broj
elemenata se odreuje konstruktorom klase, a klasa za svaku instancu (polje) mora omoguiti informaciju o broju elemenata, direktan pristup svakom elementu polja preko operatora [], te pretragu pojedine vrijednosti u polju.

42

10. Uvod u klase

Primjer 10.9.5. (Rjeenje zadatka 1)


template <class T>
class Polje
{
public:
T* polje;
int BrojElemenata;
Polje(int n);
int Sadrzi(T vrijednost);
~Polje() {delete[] polje;}
T& operator [](int indeks) {return polje[indeks];}


};
template <class T> Polje<T>::Polje(int n){
BrojElemenata = n;
polje = new T[n];
}
template <class T> int Polje<T>::Sadrzi(T Vrijednost){
int pom = 0;
for(int i = 0; i < BrojElemenata; i++)
if(polje[i] == Vrijednost)
pom = 1;
return pom;
}

Prikazani predloak klase e u konstruktoru dinamiki alocirati polje tipa T. Polje se dealocira u destruktoru, a sama klasa nudi direktan pristup tom polju preko operatora []. Takoer, funkcijskom lanicom Sadrzi vrimo pretragu polja, a lanica BrojElemenata sadri broj
elemenata polja. Na programeru je sada da samo odlui kakvo polje eli kreirati, a za svaku
instancu tog polja imati e na raspolaganju sve mogunosti ove klase. Primjerice;
Polje <int> A(100);

Odluili smo kreirati polje cijelih brojeva, a ono u ovom sluaju ima 100 elemenata. Polje je
predstavljeno varijablom (objektom) A, i sada tu varijablu zbog implementacije operatora
[] moemo koristiti kao polje:
srand((unsigned)time(NULL));
for(int i = 0; i < 100; i++)
A[i] = rand() % 100 + 1; // A.polje[i] ...

43

10. Uvod u klase

Primijetite upotrebu a zatim i implementaciju operatora []. Njegova povratna vrijednost


mora biti referenca na objekt tipa T. Kada to ne bi bila referenca onda bi operator [] mogli
koristiti samo za itanje vrijednosti nekog elementa polja, no ne i za njegovu inicijalizaciju. Inicijalizacija se striktno odnosi na objekte (varijable) jer se oni nalaze s lijeve strane
jednakosti, a ne na konstante.
Prednost koritenja predloka u ovom sluaju jest i u tome da sada direktno preko imena
instance klase doznajemo traene informacije o polju.
cout << A.Sadrzi(58);
// da li se u polju nalazi broj 58?
cout << A.BrojElemenata; // koliki je broj elemenata?

tovie, moete dodati i mnotvo drugih mogunosti. Primjerice, malom promjenom pristupa moete omoguiti direktno dinamiko proirivanje/suenje polja, implementirati
operatore za razne druge operacije s poljem, pa ak i proiriti klasu tako da moe raditi s
vie-dimenzionalnim poljima. Mogunosti su mnogobrojne, a na vama je da ih implementirate po potrebi.

44

S-ar putea să vă placă și

  • 3 VJEZBA - 3 Windows
    3 VJEZBA - 3 Windows
    Document1 pagină
    3 VJEZBA - 3 Windows
    Roko Dominis
    Încă nu există evaluări
  • Cifre (Cifre)
    Cifre (Cifre)
    Document1 pagină
    Cifre (Cifre)
    Arif Nuhanovic
    Încă nu există evaluări
  • Predavanje 3 PDF
    Predavanje 3 PDF
    Document21 pagini
    Predavanje 3 PDF
    hoxx82
    Încă nu există evaluări
  • Datoteke
    Datoteke
    Document17 pagini
    Datoteke
    Arif Nuhanovic
    Încă nu există evaluări
  • Nizovi
    Nizovi
    Document12 pagini
    Nizovi
    Arif Nuhanovic
    Încă nu există evaluări
  • C# Knjiga
    C# Knjiga
    Document86 pagini
    C# Knjiga
    gogymister2
    Încă nu există evaluări
  • Ur 07 DOS 1
    Ur 07 DOS 1
    Document15 pagini
    Ur 07 DOS 1
    Arif Nuhanovic
    Încă nu există evaluări
  • Klase U C++
    Klase U C++
    Document44 pagini
    Klase U C++
    Arif Nuhanovic
    100% (2)