You are on page 1of 8

11.10.2018.

Teme

Definiranje klase
Stvaranje objekata, članske varijable i metode
Konstruktori, destruktori
Cons funkcije
Inline funkcije

Objektno-orijentirano programiranje
u programskom jeziku C++

11.10.2018. 1 11.10.2018. 2

Klasa Klase
Klasa - skup podataka koja sadrži stanje i funkcije koje definiraju ponašanje objekata Klasa je novi tip podataka (“poopćenje strukture”: osim različitih tipova podataka
istog tipa sadrži i operacije sa modifikatorima pristupa)
Klasa predstavlja prikladan način grupiranja povezanih podataka i funkcija koje koriste
Varijable unutar klase nazivamo podatkovnim članovima ili članskim
te podatke.
varijablama (engl. data members, ili data variables)
Objekti se stvaraju (instanciraju) na temelju opisa definiranog u klasi (Abstract data type
– ADT = grupiranje operacija zajedno s podacima različitog tipa) neke članske varijable klasa Automobil: broj_vrata, broj_sjedala, godiste itd.
Pojavnost (instanca) klase i objekt su sinonimi ! Funkcije unutar klase obično manipuliraju podatkovnim članovima, a njih
nazivamo funkcijskim članovima ili metodama (engl. member functions,
methods)
ATRIBUTI:
moguće članske funkcije klase Automobil: Kreni(), Koci() itd.
nazivMarke
nazivModela Primjer klase:
serijskiBroj
KLASA kapacitet Klasa Macka:
PerilicaRublja volumenBubnja - članske var: godine, težinu;
motor
vrstaMotora - funkcije: Spavaj(), Mijau(), LoviMisa();

11.10.2018. 3 11.10.2018. 4

Deklariranje klase... Deklariranje klase...


Za deklaraciju klase, koristimo ključnu riječ class, a u bloku unutar vitičastih Deklaracija klase govori kompajleru:
zagrada upisuju se članske varijable i metode. Iza vitičaste zagrade je točka-
zarez. što je to Macka = koje članske varijable sadrži (godine i tezina) i koje
Sintaksa : ima metode (Mijau()) članska varijabla
class ImeKlase { class Macka {
// ključne riječi za kontrolu pristupa float godine; funkcijski član, metoda
// deklaracija varijabili i metoda klase float tezina;
}; Mijau();
};

Primjer deklaracija klase Macka:


class Macka { koliko je velika = koliko mjesta u memoriji treba rezervirati za svaku
float godine; mačku koja se stvori (za dvije float varijable 2 * 4 bajta -> cijela je klasa
float tezina; velika 8 bajta)
Mijau();
};

11.10.2018. 5 11.10.2018. 6

OOP – C++, M. Ivašić-Kos 1


11.10.2018.

Pravilia imenovanja Objekti, članske varijable i metode


Varijable, metode i klase imenuju se lako razumljivim imenima članske varijable imaju specifičnu Objekt Tom klase
C++ razlikuje velika i mala slova, npr. MACKA, macka, Macka; cMacka vrijednost za svaki objekt Macka
(klasa Macka) godine = 1.5
metode se definiraju na razini klase tezina = 2
imena klase se najčešće pišu velikim početnim slovom te svi objekti koriste iste metode Metode: Mijau();
imena varijabli i metoda najčešće se pišu malim početnim slovom
složene nazive metoda ili varijabli mogu se pisati spojeno ili odvojeno, npr. Objekt MicaMaca
loviMisa(), LoviMisa(), Lovi_Misa() klase Macka
godine = 2
Klasa Macka
tezina = 3.3
Preporuka je da se odabrani način koristi tijekom cijelog programa Metode: Mijau();
Članske varijable:
float godine;
float tezina;
Objekt Suzi
Metode:
klase Macka
Mijau();
godine = 3
tezina =2.5
Metode: Mijau();
11.10.2018. 7 11.10.2018. 8 8

Struktura objekata Stvaranje objekata

svaki objekt ima: Objekt je instanca klase.


atribute (svojstva, stanje) class Macka { Opisom klase nije načinjena pojavnost objekta
- podatkovni dio objekata float godine; Objekti postoje u vremenu, promjenjivi su, imaju stanje, stvaraju se i
- svaki objekt ima vlastite vrijednosti atributa float tezina; uništavaju, te mogu biti dijeljeni
// … ponašanje
}; Stvaranje objekta klase Macka u C++: alokacja mem.
Objekt Tom:
Macka Tom;
godine
metode (ponašanje) class Macka {
- operacije koje objekt nudi // … stanje tezina
- operacije se izvršavaju nad objektom Mijau(); Analogija sa jednostavnim tipovima:
- operacije mogu utjecati na atribute objekta };
int tezina; //definicija cijelog broja alokacja mem.
- u C++ se govori se da objekt koji poziva člansku funkciju drugog objekta za var i:
tezina

11.10.2018. 9 11.10.2018. 10

Životni vijek objekata (faze) Pristupanje članovima klase (dot operator)


Jednom kad definiramo objekt klase Macka (npr. Tom), korištenjem
alokacija memorije za objekt operatora točke (.) pristupamo članovima toga objekta
objekt se automatski smješta Automatski!
Stog
na stog Npr. poziv Mijau() funkcije:
pomoću operatora new() alokacija stvaranje Tom.Mijau();
moguć je smještaj na gomilu Npr. postavljanje vrijednosti članskoj varijabli tezina (kad je pristup dozvoljen):
(heap) – (primjer kasnije) hrpa: new()
objekt
Tom.tezina = 2.5;
stvaranje objekta
korištenje
korištenje objekta U C++ ne pridružujemo vrijednosti tipovima, nego varijablama.
uništavanje objekta objekt Stog float = 5; // pogrešno je ispravno: float x;
x = 5;
oslobađanje memorije
uništavanje oslobađanje
bitovi
Macka.godine=5; // pogreška Macka Tom;
hrpa: delete() Tom.godine = 5;
Pod kontrolom korisnika!

11.10.2018. 11 11.10.2018. 12

OOP – C++, M. Ivašić-Kos 2


11.10.2018.

Pristupanje članovima klase (dot operator) Životni vijek objekata (faze)


Npr. poziv Mijau() funkcije:
alokacija memorije za objekt
Tom.Mijau();
stvaranje objekta
korištenje objekta Automatski!
objekt naziv metode Stog
uništavanje objekta Macka Tom;

oslobađanje memorije alokacija stvaranje

Tom.dimenzije(float visina,float duljina); objekt


Tom.tezina =2;
objekt naziv metode parametri

korištenje Tom.Mijau();

objekt Stog
Npr. postavljanje vrijednosti članskoj varijabli tezina (kad je pristup dozvoljen):
Tom.tezina = 2.5; uništavanje oslobađanje
bitovi

objekt članska varijabla

11.10.2018. 13
11.10.2018. 14

Osnovni cilj prilikom stvaranja klase Modifikatori vidljivosti

Sakriti informacije o podacima i implementaciji u privatni dio klase s pomoću modifikatora vidljivosti ograničava se pristup
(enkapsulacija - skrivanje) – klasa kao “crna kutija” ograničavanje pristupa provodi se već pri prevođenju programa
Javno prikazati skup operacija koja će se primjenjivati na instancama članovi klasa imaju tri modifikatora vidljivosti:
klase (sučelje) public – javne članske varijable i funkcije vidljive su svakom objektu klase i svim
Prava pristupa ograničavaju se modifikatorima vidljivosti. korisnicima koji imaju pristup klasi
private – privatne članske varijable i funkcije vidljive su samo funkcijama klase u
Klase nas “prisiljavaju” da sučelje i implementaciju potpuno odvajamo,
kojoj su definirane
čak i kada to zahtijeva “više posla”.
protected – zaštićene članske varijable i funkcije vidljive su u klasi kojoj su
definirane i u klasama koje su ju javno nasljedile (detalji kod nasljeđivanja)

Zadano je (default) da su svi članovi klase (i podaci i metode) privatni!


Privatnim članovima možemo pristupiti samo iz metoda klase u kojoj se
nalaze!

11.10.2018. 15 11.10.2018. 16

Privatno i javno Privatno i javno


Možemo pristupati podatkovnim članovima i metodama klase Macka ako Ne možemo pristupati podatkovnim članovima i metodama klase Macka
je definiran javni pristup (public): ako je definiran pristup private:
class Macka { class Macka {
public: // ako nije navedeno smatra se da je
float godine; // pristup private:
float tezina; float godine;
Mijau(); float tezina;
}; Mijau();
};
int main() { int main() {
Macka MicaMaca; Macka MicaMaca;
MicaMaca.godine = 5; //pridruživanje vrijed. čl.varijabli MicaMaca.godine = 5;
cout << “MicaMaca ima “ <<MicaMaca.godine<<“godina\n”; /* Greška!
return 0; Ne može se pristupati privatnim podacima! */
} …..
return 0;
}

11.10.2018. 17 11.10.2018. 18

OOP – C++, M. Ivašić-Kos 3


11.10.2018.

Privatne članske varijable i metode pristupa Javno sučelje objekta


// Deklaracija klase
class Macka { // Deklaracija klase
Da bismo mogli pristupati članovima klase class Macka {
public:
koji su privatni kreiraju se javne metode public:
// javne metode pristupa pristupa (engl. accessor methods) // javne metode pristupa javno sučelje objekta
float getGodine(); za postavljanje vrijednosti privatnih varijabli float getGodine(); čine javne metode
void setGodine(float pGodine); (set) void setGodine(float pGodine);
koristi se za komunikaciju s
float getTezina();
za vraćanje vrijednosti privatnih varijabli float getTezina(); ostalim objektima/metodama
(get) void setTezina(float pTezina); omogućuje objekt da izlaže samo
void setTezina(float pTezina);
Javne metode čine sučelje za korištenje one članske varijable/metode za
// javne članske funkcije // javne članske funkcije koje smatra da trebaju biti vidljive
klase i pristup privatnim podatkovnim
void Miau(); void Miau();
članovima neke klase ostatku svijeta
// privatni članovi // privatni članovi
private:
private: float godine;
float godine; Svaki programer može izbjeći float tezina;
float tezina; privatnost ako to želi };
};
11.10.2018. 19 11.10.2018. 20

Javno sučelje Implementacija metoda klase


javnim sučeljem objekt izlaže samo Pristupna funkcija pruža javno sučelje za privatne podatkovne članove
// Deklaracija klase one članske varijable/metode za neke klase
class Macka {
public: koje smatra da trebaju biti vidljive Implementacija pristupne funkcije ili metode je njena definicija
// javne metode pristupa
float getGodine();
Definicija funkcijskog člana počinje s imenom klase, kojeg slijedi operator
void setGodine(float pGodine); // stvaranje objekata i određivanja dosega (::), ime funkcije, te njezini parametri
pozivanje javnih metoda Operator određivanja dosega koristi se kako bi se naznačila klasa kojoj
float getTezina(); metode pripadaju (npr. klasi Macka)
void setTezina(float pTezina); int main() {
Macka Frisky;
Frisky.setGodine(5); // implementacija
// javne članske funkcije
Frisky.Miau();
void Miau(); float Macka::getGodine() { return godine; }
cout << “Frisky je mačka
koja ima“ ; void Macka::setGodine (float pGodine) {
// privatni članovi cout<<Frisky.getGodine()
private: godine = pGodine;
<<“ godina \n”; }
float godine; Frisky.Miau();
float tezina; return 0; void Macka::Miau() { cout << “Miau.\n”; }
}; }

11.10.2018. 21 11.10.2018. 22

Primjer 3. Stvaranje i inicijalizacija objekata


#include <iostream> int main() { za inicijalizaciju, zadavanja početnog stanja objekta koristi se konstruktor
Macka Frisky; konstruktor (inicijalizacijski postupak; analogno int tezina = 7; )
class Macka{
Frisky.setGodine(5);
public: // javni dio metoda koje se automatski poziva prilikom stvaranja objekta i koja ima isto ime
// pristupna funkcija Frisky.Miau();
float getGodine(); std::cout << “Frisky ie mačka kao i klasa; Primjer konstruktora za klasu Mačka: Macka();
void setGodine (float pGodine); koja ima “ ; može imati parametre, ali nema povratnu vrijednost niti void
// članska funkcija std::cout<<Frisky.getGodine()
void Miau(); << “ godina\n”; klasa/objekt može imati više konstruktora (preopterećivanje), ali prilikom
private: // privatni dio Frisky.Miau(); stvaranje objekta poziva se samo jedan konstruktor
float godine; //članska var. return 0;
}; class ImeKlase {
}
public:
float Macka::getGodine(){ ImeKlase(); //konstruktor bez parametara
return godine; IZLAZ PROGRAMA:
}
ImeKlase(tip par1); // konstruktor s parametrom
Miau.
void Macka::setGodine(float pGodine){ ImeKlase(tip par1, tip par2, …tip park);
godine = pGodine; Frisky je mačka koja
// deklaracija metoda klase
} ima 5 godina.
// ključne riječi za kontrolu pristupa
void Macka::Miau() { Miau. // deklaracija varijabili
std::cout << “Miau.\n”;
}
};
11.10.2018. 23 11.10.2018. 24

OOP – C++, M. Ivašić-Kos 4


11.10.2018.

Uništavanje objekata Životni vijek objekata (faze)


za oslobađanje resursa za koje nema smisla da budu zauzeti nakon što je
alokacija memorije za objekt
objekt postao nepotreban (kraj funkcije ili programa; naredba delete)
koristi se destruktor stvaranje objekta
destruktor korištenje objekta Stog
Automatski!

uništavanje objekta Macka Tom;


metoda koje se automatski poziva prilikom uništavanja objekta i koja ima isto
ime kao i klasa, uz prefiks ~; Primjer destruktora za klasu Macka: ~Macka(); oslobađanje memorije alokacija stvaranje Macka();

ne može imati ni povratne vrijednosti niti parametara objekt


Tom.SetTezina(2);
klasa/objekt može imati samo jedan destruktor

class ImeKlase { korištenje Tom.Mijau();
public:
ImeKlase(); objekt ~Macka(); Stog
ImeKlase(tip par1, tip par2, …tip park);
~ImeKlase(); //destruktor uništavanje oslobađanje
bitovi
// deklaracija metoda klase i varijabili
};

11.10.2018. 25
11.10.2018. 26

Podrazumijevani konstruktori i destruktori Primjer: Konstruktor bez parametara


Kad god stvorimo objekt neke klase, poziva se konstruktor. class Pravokutnik {
double visina; #include <iostream>
Kad god prestanemo koristiti objekt neke klase, poziva se destruktor. using namespace std;
double sirina;

Ako u klasi ne deklariramo konstruktor, automatski se stvara public: void main() {


podrazumijevani (default) konstruktor sa praznim tijelom, bez parametara Pravokutnik() { Pravokutnik mali;
kod stvaranja niza objekata podrazumijevani konstruktor inicijalizira sve parametre sa visina = 5; cout<<" Površina
podrazumijevanom vrijednosti (primjer kasnije) sirina = 10;
pravokutnika je " <<
mali.povrsinaPrav ();
Ako u klasi postoje definirani konstruktori, podrazumijevani se konstruktor }
}
neće automatski stvoriti ~ Pravokutnik(){}

Destruktori se pozivaju redoslijedom obrnutim od redoslijeda poziva


double povrsinaPrav () {
konstruktora double povrsina;
Npr. prilikom stvaranja objekta: povrsina = visina*sirina;
Macka Frisky; // Frisky ne dobiva nikakve parametre return povrsina;
tada se poziva se konstruktor u obliku: Macka(); }
};
11.10.2018. 27 11.10.2018. 28

Podrazumijevani konstruktori vs. inicijalizacija primitivnih tipova Primjer: Konstruktor s parametrima


class Pravokutnik {
alokacja mem. za Objekt mali double visina; #include <iostream>
i inicijalizacija: using namespace std;
double sirina;
Objektni tipovi visina 5.0 public: void main() {
Pravokutnik mali;
sirina 10.0 Pravokutnik(double v, double s){ Pravokutnik mali (15,20);
visina = v; cout<<" Površina
pravokutnika je " <<
sirina = s;
mali.povrsinaPrav ();
}
alokacja mem. za var visina }
~ Pravokutnik(){}
tipa double i inicijalizacija
Jednostavni tipovi:
double povrsinaPrav () {
double visina = 5; visina 5.0 return visina*sirina;
}
};

11.10.2018. 29 11.10.2018. 30

OOP – C++, M. Ivašić-Kos 5


11.10.2018.

Podrazumijevani konstruktori vs. inicijalizacija primitivnih tipova Inicijalizacija konstruktora inicijalizacijskom listom
alokacja mem. za Objekt mali
i inicijalizacija: Inicijalizacijska lista omogućuje prosljeđivanje vrijednosti:
konstruktorima članske varijable
v=15; visina = v
Objektni tipovi konstruktorima nadklase
visina 15.0
Pravokutnik mali(15,20);
sirina 20.0 Koristi se () forma inicijalizacije tako da su inicijalizacijske vrijednosti
unutar (), a nakon parametara konstruktora koristi se operator :
s=20; sirina = s

Pravokutnik(double v, double s) : visina(v), sirina (s)


alokacja mem. za var visina {}
Jednostavni tipovi: tipa double i inicijalizacija
double v = 15; visina 15.0
double visina = v;

11.10.2018. 31 11.10.2018. 32

Inicijalizacija Vs. Pridruživanje Preopterećivanje konstruktora


Možemo i sami napisati konstruktor sa ili bez parametara
Pravokutnik(double v, double s){ Pravokutnik(double v,
Klasa može imati više konstruktora – preopterećivanje (overloading) - moraju
visina = v; double s): visina(v),
se razlikovati po listi i/ili tipovima parametara
sirina = s; sirina(s){}
Ako deklariramo konstruktor, dobra praksa je deklarirati i destruktor
}
Macka() {
slično kao: deklaracija + slično kao: godine = 0;
pridruživanje: inicijalizacija: } ~Macka(); //
int i; destruktor
int i =5; Macka(float initGodine) {
i = 5;
godine = initGodine;
Inicijalizacijska lista }
može biti brža kada su
članske varijable Prilikom stvaranja objekta, pozivamo odgovarajući konstruktor
objekti ili strukture Ako ne šaljemo niti jedan parametar, pišemo i pozivamo konstruktor bez parametara:
Izbjegava se nepotrebni Macka Tom;
poziv default Ako šaljemo jedan parametar, pišemo i pozivamo odgovarajući konstruktor:
konstruktora Macka Frisky (3);
11.10.2018. 33 11.10.2018. 34

Primjer: Preopterećivanje konstruktora Preopterećivanje funkcijskih članova


class Pravokutnik { nazivanje više funkcija istim imenom nazivamo preopterećivanje funkcija
double visina; #include <iostream>
using namespace std;
(overloading) - funkcijski polimorfizam (“polimorf” - više oblika)
double sirina;
public: void main() { sve što vrijedi kod preopterećivanja funkcija vrijedi i kod preopterećivanja
Pravokutnik(){ Pravokutnik prvi; funkcijskih članova klase:
visina = 0; cout<<" Površina preopterećene funkcije moraju se razlikovati po listi parametara, tipovima parametara,
pravokutnika je " << ili oboje
sirina = 0;
prvi.povrsinaPrav ();
} povratni tip može biti isti ili različit za preopterećene funkcije
Pravokutnik(double v, double s){
Pravokutnik mali (5,10);
visina = v;
cout<<" Površina Primjer preopterećenihčlanskih funkcija:
sirina = s; pravokutnika je " <<
}
void Macka::setTezina(int pTezina);
mali.povrsinaPrav ();
void Macka:: setTezina(float pTezina);
~ Pravokutnik() {}
} Primjer poziva preopterećenih članskih funkcija:
double povrsinaPrav () {
Tom.setTezina(2);
return visina*sirina; MicaMaca.setTezina(0.5);
}
}; 11.10.2018. 35 11.10.2018. 36

OOP – C++, M. Ivašić-Kos 6


11.10.2018.

#include <iostream> using


Primjer 4. namespace std;
int main() {
Konstantni funkcijski članovi...
class Macka{ Macka Frisky(5);
public: Frisky.Miau(); Metoda klase koja je deklarirana kao const, ne može promijeniti
Macka(); cout << “Frisky ima “ ; vrijednost niti jednog člana klase
Macka(float initGodine); cout << Frisky.getGodine()
<< “ godina. \n”;
Sintaksa: ključna riječ const piše se nakon zagrade, prije točke-zarez:
~Macka(){}
float getGodine(){return godine;} Frisky.Miau(3); void NekaFunkcija() const;
Frisky.setGodine(7);
void setGodine(float pGodine);
cout << “Sada Frisky ima “;
void Miau();
cout << Frisky.getGodine() Ako je metoda deklarirana kao const, a njezina implementacija mijenja
void Miau(int a); << “ godina.\n”; vrijednost nekog podatkovnog člana, kompajler će javiti grešku!
private: return 0;
float godine; }
}; Dobra je programerska praksa deklarirati metode kao const kad god je to
Macka::Macka(){godine = 0;} moguće.
Macka::Macka(float iGod){godine =iGod;} Pristupne funkcije deklariramo konstantnima kada je moguće.
IZLAZ PROGRAMA:
void Macka::setGodine (float pGod) {godine Miau. Npr. setGodina() ne može biti const budući da mijenja podatkovni član, varijabla
= pGod;} godine, ali getGodina() može.
Frisky ima 5 godina.
void Macka::Miau() {cout << “Miau.\n”; }
void Macka::Miau (int a){
Miau. Miau. Miau. void setGodina(float godina);
Sada Frisky ima 7
for(int i=0; i<a; i++, cout<<“Miau.“);
godina.
float getGodina() const;
cout<< endl;}
11.10.2018. 37 11.10.2018. 38

Gdje staviti deklaracije klasa i definicije metoda Deklaracija i definicija klase


Deklaraciju klase i definiciju članskih funkcija možemo zajedno pisati u .cpp
datoteke, ali to nije dobra programerska praksa DemoClass.h DemoClass.cpp
Deklaracija klase govori kompajleru što je klasa, koje podatke sadrži, te koje class DemoClass { #include "DemoClass.h“
funkcije ima = sučelje (engl. interface) public: DemoClass::DemoClass(int
Sučelje se obično sprema u datoteku zaglavlja (engl. header file), .hpp DemoClass(int iValue =-1); iValue): m_iValue(iValue)
datoteku ~DemoClass(); {//kod …}
Svaka članska funkcija klase ima deklaraciju i definiciju int getValue(); DemoClass::~DemoClass(){}
void setValue (int iValue);
Definicija članske funkcije govori kompajleru kako funkcija radi = private: int DemoClass::getValue()
implementacija funkcije (koja se tiče autora, a ne korisnika klase) int m_iValue; {return m_iValue;}
Definicija funkcije sprema se u .cpp datoteci. };
void
Npr., ako je deklaracija klase Macka u datoteci Macka.hpp, a definicija
DemoClass::setValue(int
metoda u Macka.cpp, tada se datoteka zaglavlja uključuje u .cpp datoteku: iValue )
#include Macka.hpp Ako parametri funkcije imaju
{m_iValue = iValue; }
zadanu vrijednost - > piše ju se u
deklaraciji a na u definiciji!
11.10.2018. 39 11.10.2018. 40

“Inline” implementacija Primjer 5.


Ključna riječ inline stavlja se ispred povratnog tipa funkcije Članske funkcije koje su definirane unutar klase, automatski su
Kompajler će pokušati cijelo tijelo funkcije zalijepiti na mjesto poziva (implicitno) definirane kao inline.
zato tijelo inline funkcije mora biti vidljivo u svakoj datoteci koja koristi inline funkciju
zato je dobro inline funkciju definirati u zaglavlju u kojem je deklarirana i klasa #include <iostream>
class Macka {
Inline implementacija funkcije getTezina(), na primjer, izgleda ovako:
public:
inline float Macka::getTezina(){ // inline!
Macka (float initGodine) {godine = initGodine;};
return tezina;
~Macka() {};
} float getGodine() const {return godine;}
void setGodine (float pGodine) {godine = pGodine;}
void Miau() const {std::cout << “Miau.\n”;}
Drugi način je staviti definiciju funkcije u deklaraciju same klase, što
automatski čini člansku funkciju inline private:
float godine;
};

11.10.2018. 41 11.10.2018. 42

OOP – C++, M. Ivašić-Kos 7


11.10.2018.

Usporedba Klase -Strukture Kviz

Struktura je vrlo slična Klasi. Kako definirati novu klasu i stvarati objekte te klase?
Kod strukture ključna riječ struct, a deklaracija je jednaka kao ona kod Što su funkcijski članovi i podatkovni članovi (engl. member function &
klase. member data)?
U C++, struktura je isto što i klasa, osim što su članovi strukture javni po Što su konstruktori, a što destruktori?
defaultu Što su privatni, a što javni objekti?
Kako napraviti datoteku zaglavlja?

11.10.2018. 43 11.10.2018. 44

OOP – C++, M. Ivašić-Kos 8

You might also like