You are on page 1of 18

Elektrotehniki fakultet

Banja Luka

Programski jezici 1

KLASE I APSTRAKCIJA PODATAKA

2. dio

Goran Banjac
goran.banjac@etfbl.net

12/3/15

Klase 2. dio
Sadraj

Konstantni objekti i konstantne lanice klase


Pokaziva this
Kompozicija: OBJEKAT kao ATRIBUT
Statiki (zajedniki) lanovi klase

Konstantni objekti i konstantne


lanice
Konstantni objekti

Konstantni objekti (read-only)


definiu se navoenjem kljune
rijei const (kao i instance
ugraenih tipova).
Primjer:

class Time
{
public:
Time(int h=0,int m=0,int s=0)
{ hh=h; mm=m; ss=s; }
private:
int hh, mm, ss;
};
...
const Time podne(12);
const Time ponoc;

Svaki pokuaj da se promijeni


vrijednost konstantnog objekta bie
okarakterisan kao sintaksna
greka!!!

Konstantni objekti i konstantne


lanice
Konstantne funkcije lanice

Da bi kompajler omoguio poziv


funkcije lanice za konstantne
objekte funkcija lanica takoe
mora biti definisana kao
konstantna. (Ovo vai i za get
funkcije!)
Funkcija lanica se proglaava
konstantnom tako to se (i u
prototipu i u definiciji funkcije) iza
Ako
za datu klasu
nee definisati
listese
parametara
navede
const.
konstantni objekti, funkcije lanice ne
moraju da se definiu kao konstantne.

Ako se za neku klasu i definie


konstantan objekat, ali se za taj objekat
nee pozivati funkcije lanice, ni tada
funkcije lanice ne moraju da se definiu
kao konstantne.

Za konstruktore i destruktore ne
moe da se koristi const!

Iz konstruktora je dozvoljeno i mogue


pozivati funkcije lanice koje nisu
konstantne.

Primjer:

class Time
{
public:
Time(int h=0,int m=0,int s=0)
{ hh=h; mm=m; ss=s; }
int getSat() const;
private:
int hh, mm, ss;
};
...
int Time::getSat() const
{ return hh; }

Konstantni objekti i konstantne


lanice
Primjer:
int main()
#include <iostream>
{
#include <cmath>
Tacka tA(3,4);
#define K(a,b) pow(((a)-(b)),2)
const Tacka tO; // konstantan objekat
using namespace std;
cout<<"A: "<<tA.getX()<<","<<tA.getY()<<endl;
class Tacka
{
cout<<"O: "<<tO.getX()<<","<<tO.getY()<<endl;
public:
cout<<"A: "; tA.pisiTacka(); cout<<endl;
Tacka (double=0, double=0);
cout<<"O: "; tO.pisiTacka(); cout<<endl;
double getX() const;
double getY() const;
cout << "Udaljenost od A"; tA.pisiTacka();
double daljina(Tacka) const;
cout << " do O"; tO.pisiTacka();
void pisiTacka() const;
cout << " iznosi: " << tA.daljina(tO) << endl;
private:
cout << "Udaljenost od O"; tO.pisiTacka();
double x, y;
cout << " do A"; tA.pisiTacka();
};
cout << " iznosi: " << tO.daljina(tA) << endl;
Tacka::Tacka(double xx, double yy)
}
{ x = xx; y = yy; }
double Tacka::getX() const
{ return x; }
A: 3,4
double Tacka::getY() const
O: 0,0
A: (3,4)
{ return y; }
O: (0,0)
double Tacka::daljina(Tacka t) const
Udaljenost od A(3,4) do O(0,0) iznosi: 5
{ return sqrt(K(x,t.x)+K(y,t.y)); }
Udaljenost od O(0,0) do A(3,4) iznosi: 5
void Tacka::pisiTacka() const
{ cout << "("<<x<<","<<y<<")"; }

Konstantni objekti i konstantne


lanice
Konstantni podaci lanovi

Klasa moe da sadri i


konstantne podatke lanove.
Tada e kreirani objekti imati
konstantne atribute.

Inicijalizacija konstantnih
atributa ne moe da se vri u
tijelu konstruktora
korienjem operatora dodjele,
ve pomou inicijalizatora.

Primjer:

class Brojac
{
private:
int stanje;
const int korak;
public:
Brojac(int b, int k) : korak(k)
{ stanje = b; }
};

Inicijalizacija atributa koji nisu konstantni takoe moe da se vri na isti


nain.
class Brojac
{
private:
int stanje;
const int korak;
public:
Brojac(int b, int k) : stanje(b), korak(k) {};
};

Konstantni objekti i konstantne


lanice
Primjer:
#include <iostream>
using namespace std;
class Inkrement
{
public:
Inkrement( int b=0, int i=1 );
void dodaj() { stanje += korak; }
void print();
private:
int stanje;
const int korak;
};

Prije petlje : stanje=10, korak=5


stanje=15, korak=5
stanje=20, korak=5
stanje=25, korak=5

Inkrement::Inkrement(int b,int i) : korak (i) { stanje = b; }


void Inkrement::print()
{
cout << "stanje=" << stanje << ", korak=" << korak << endl;
}
int main()
{
Inkrement data(10,5);
cout << "Prije petlje : ";
data.print();
for ( int j=1; j<4; j++ ) { data.dodaj(); data.print(); }
}

Pokaziva this

Osim formalnih argumenata, funkcije lanice imaju i jedan


skriveni argument (skriveni ne vidi se u prototipu).

Taj skriveni argument je tekui objekat objekat za koji je


pozvana funkcija lanica.

Adresa skrivenog argumenta (tekueg objekta), za


vrijeme izvravanja funkcije lanice, nalazi se u
pokazivau this.

Svaki objekat ima pristup svojoj vlastitoj adresi preko


pokazivaa this.

Pokaziva this koristi se implicitno za referenciranje lanica i ne


mora da se navodi (kao u dosadanjim primjerima).

Pokaziva this moe da se koristi i eksplicitno!

Ako je tekui objekat vrijednost koju vraa data funkcija lanica,

Ako je tekui objekat argument neke funkcije,

Za kaskadno pozivanje funkcija.

Pokaziva this
Primjer:
#include <iostream>
using namespace std;
x = 12
class Test
this->x = 12
{
(*this).x = 12
public:
arg x = 100
Test(int a=0) { x=a; };
clan x = 12
void print() const;
void maska(int) const;
private:
int x;
};
void Test::print() const
{
cout << "x = " << x << endl;
cout << "this->x = " << this->x << endl;
cout << "(*this).x = " << (*this).x << endl;
}
void Test::maska(int x) const
{
cout << "arg x = " << x << endl;
cout << "clan x = " << this->x << endl;
}
int main()
{ Test t(12); t.print(); t.maska(100); }

Pokaziva this
Primjer:
#include <iostream>
using namespace std;
class Time
{
public:
Time &setTime(int, int);
Time &setSat(int);
Time &setMin(int);
void print();
private:
int sat, min;
};
Time &Time::setTime(int h, int m)
{ setSat(h); setMin(m); return *this; }
Time &Time::setSat(int h)
{
sat = (h>=0 && h<24) ? h : 0;
return *this;
}
Time &Time::setMin(int m)
{
min = (m>=0 && m<60) ? m : 0;
return *this;
}

void Time::print()
{
cout << ( sat<10 ? "0":"" ) << sat;
cout << ":" ;
cout << ( min<10 ? "0":"" ) << min;
}
int main()
{
Time t;
t.setSat(18).setMin(5);
cout << "Vrijeme : "; t.print();
cout << "\nNovo vrijeme : ";
t.setTime(20,30).print();
}

Vrijeme : 18:05
Novo vrijeme : 20:30

Pokaziva this
Primjer:
a=1+i
|a|=1.41421
#include <iostream>
b=2
|b|=2
#include <cmath>
c=i
|c|=1
using namespace std;
d=3-4i |d|=5
class Complex;
double moduo(Complex);
class Complex
{
public: Complex(char s, double r=0, double i=0) : c(s), re(r), im(i) {};
double getRe() { return re; }
double getIm() { return im; }
void printComplex()
{
cout << c << "=";
if (re!=0) { cout << re; if (im>0) cout << "+"; }
if (im!=0) { if (im!=1) cout << im; cout << "i"; }
cout << "\t|" << c << "|=" << moduo(*this) << endl;
}
private: double re, im;
char c;
};
double moduo(Complex c)
{ return pow(pow(c.getRe(),2.0)+pow(c.getIm(),2.0),0.5); }
int main()
{
Complex a('a',1,1), b('b',2), c('c',0,1), d('d',3, -4);
a.printComplex(); b.printComplex(); c.printComplex(); d.printComplex();
}

Kompozicija: OBJEKAT kao ATRIBUT

Podatak lan u nekoj klasi moe da bude objekat (instanca neke klase).
Kad neki objekat ima neki drugi objekat kao atribut, govorimo o
kompoziciji.
Objekat moe da sadri jedan ili vie objekata drugih klasa (automobil
ima tokove, sjedita, volan, ...), tj. klasa moe da sadri vie podataka
lanova
koji su instance nekih drugih klasa.
Primjer:
class Datum
{
public:
Datum(int=1, int=1, int=2000);
~Datum();
private:
int dan, mjesec, godina;
};

class Osoba
{
public:
Osoba(char *, int, int, int);
~Osoba();
private:
char ime[15];
const Datum rodjen;
};

Kompozicija ne moe da postoji ako nema objekata koji je ine. Zato se


prilikom kreiranja nekog sloenog objekta (kompozicija), prvo kreiraju
svi podobjekti, a zatim objekat koji ih sadri (host objekat).

Prvo se pozivaju i izvravaju konstruktori za podobjekte (redom kojim


su navedeni u definiciji klase, a ne redom kojim su navedeni u listi
inicijalizatora konstruktora host objekta), a na kraju konstruktor host

Kompozicija: OBJEKAT kao ATRIBUT


Primjer:
#include <iostream>
using namespace std;
class X {
YXA
public: X(int i=0) : x(i) { cout << "X"; }
Objekat klase A sadrzi:
int getX() { return x; }
podobjekat klase X: 1
private: int x;
podobjekat klase Y: 2
};
podatak tipa int:
3
class Y {
public: Y(int i=0) : y(i) { cout << "Y"; }
int getY() { return y; }
private: int y;
};
class A {
public:
A(int i=1, int j=2, int k=3): a(k), x(i), y(j) { cout << "A" << endl; }
void print()
{
cout << "Objekat klase A sadrzi:" << endl;
cout << "
podobjekat klase X: " << x.getX() << endl;
cout << "
podobjekat klase Y: " << y.getY() << endl;
cout << "
podatak tipa int:
" << a << endl;
}
private: Y y; X x; int a;
};
int main() { A obj; obj.print(); }

Kompozicija: OBJEKAT kao ATRIBUT


Primjer:
#include <iostream>
using namespace std;
class Datum
{
public:
Datum(int d=1, int m=1, int g=2000)
{
gg = g;
mm = (m>0 && m<=12) ? m : 1;
dd = provjeriDan(d);
cout<<"Kon. datuma: "; print();
}
void print() const
{ cout<<dd<<'.'<<mm<<'.'<<gg<<'.'<<endl;}
Kon. datuma:
28.2.1975.
~Datum()
Kon. osobe : Marko
{ cout<<"Dest.
datuma: "; print(); }
Kon. datuma:
29.2.2000.
private:
Kon. osobe : Janko
int
dd, mm,
gg;
Kon.
datuma:
1.2.1900.
int
provjeriDan(int
dan)
Kon.
osobe
: Slavko
{
Marko je rodjen: 28.2.1975.
static
const
int m[13] =
Janko je
rodjen:
29.2.2000.
{0,31,28,31,30,31,30,31,31,30,31,30,31};
Slavko je rodjen: 1.2.1900.
if (dan>0
&& dan<=m[mm]) return dan;
Dest. osobe
: Slavko
if (mm==2
&& dan==29 &&
Dest. datuma:
1.2.1900.
(gg%400==0
|| (gg%4==0 && gg%100!=0)))
Dest. osobe : Janko
return
dan;
Dest. datuma:
29.2.2000.
return
1;
Dest. osobe : Marko
Dest.}datuma: 28.2.1975.
};

class Osoba
{
public:
Osoba(char *s, int d, int m, int g) :
rodjen(d,m,g)
{
int bs=0;
while ((ime[bs]=*(s+bs)) && bs<14) bs++;
if (bs==14) ime[bs]='\0';
cout <<"Kon. osobe : "<<ime<<endl;
}
void print() const
{
cout << ime << " je rodjen: ";
rodjen.print();
}
~Osoba()
{ cout << "Dest. osobe : "<<ime<<endl; }
private:
char ime[15];
const Datum rodjen;
};
int main()
{
Osoba otac ("Marko", 28,2,1975),
sin ("Janko", 29,2,2000),
pradeda("Slavko",29,2,1900);
otac.print(); sin.print(); pradeda.print();
}

Statiki (zajedniki) lanovi klase

Prilikom definisanja klase, lanice mogu da se proglase statikim


(kvalifikator static ispred lanice).

Statiki lan klase je zajedniki za sve objekte date klase koji su


stvoreni tokom izvravanja programa.

lanice klase koje nisu zajednike, nazivaju se pojedinane lanice


klase.

I podaci i funkcije lanice mogu biti zajedniki lanovi klase.

Zajedniki podaci lanovi

Ako je podatak lan zajedniki lan


klase, to znai da postoji samo jedan
primjerak tog atributa, bez obzira na
broj objekata.

Pristup zajednikom atributu je


pristup istoj memorijskoj lokaciji za
sve objekte.

Mijenjanjem vrijednosti zajednikog


atributa utie se na stanje svih
objekata te klase.

Primjer:
class Klasa
{
...
static int a; // zajednicki clan
int b; // pojedinacni clan
...
};
// obavezna inicijalizacija statickog atributa

int Klasa::a = 55;

Statiki (zajedniki) lanovi klase


Primjer:
#include <iostream>
using namespace std;
class Komuna
{
public:
Komuna(char c) : naziv(c)
{
cout << ++brojac << ". objekat zove se: " << naziv
}
private:
static int brojac; // ZP
char naziv;
// PP
};
int Komuna::brojac = 0; // inicijalizacija ZP
int main()
{
1. objekat zove
Komuna a('A'), b('B'), c('C');
2. objekat zove
}
3. objekat zove

<< endl;

se: A
se: B
se: C

Statiki (zajedniki) lanovi klase


Zajednike funkcije lanice

Zajednike funkcije lanice ne


posjeduju pokaziva this.
Zajednike funkcije lanice
pristupaju zajednikom atributu
direktnim referenciranjem atributa.
Primjer:
class Klasa
{
static int a;
public:
static int f()
{
cout << ++a;
}
};
int Klasa::a=0;

Zajednike funkcije lanice pristupaju


pojedinanom atributu nekog objekta
referenciranjem objekta kojem pripada
taj atribut.
Primjer:
class Klasa
{
int x;
public:
static int g(Klasa &a, Klasa *b)
{
cout << a.x;
cout << b->x;
}
};

Pojedinane funkcije lanice mogu


direktno da pristupe i pojedinanim i
zajednikim atributima.

Statiki (zajedniki) lanovi klase


Primjer:
class Klasa
{
static int a; // ZP
int b;
// PP
public:
int h(int); // PF
static int f(); // ZF
static void g (Klasa, Klasa *, Klasa &); //
ZF
};
int Klasa::a=55; // inicijalizacija ZP
int Klasa::f()
{
int i=a; // ZF moze da pristupi ZP
int j=b; // ERR - ZF ne moze da pristupi PP int main()
{
return i+j;
// poziv ZF bez konkretnog objekta
}
int p=Klasa::f();
void Klasa::g(Klasa x, Klasa *y, Klasa &z)
{
// ERR - poziv PF ne moze bez objekta
int i = x.b; // ZF moze da pristupi
int q=Klasa::h(5);
int j = y->b; // PP konkretnih objekata
Klasa k;
z.b = i + j;
Klasa::g(k,&k,k); // poziv ZF
}
int s=k.h(6);
// poziv PF
int Klasa::h( int x ) // PF moze da
}
{ return (a+b)*x; }
// pristupa i PP i ZP

You might also like