Upload
milana-tomic
View
216
Download
0
Embed Size (px)
DESCRIPTION
C++
Citation preview
Programski jezici 1
2. dio
Elektrotehnički fakultetBanja Luka
KLASE I APSTRAKCIJA PODATAKA
Goran [email protected]
04/22/2023
Klase – 2. dio
Sadržaj Konstantni objekti i konstantne članice klase Pokazivač this Kompozicija: OBJEKAT kao ATRIBUT Statički (zajednički) članovi klase
Konstantni objekti i konstantne članice
Konstantni objekti Konstantni objekti (read-only)
definišu se navođenjem ključne riječi const (kao i instance ugrađenih 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 pokušaj da se promijeni
vrijednost konstantnog objekta biće okarakterisan kao sintaksna
greška!!!
Konstantni objekti i konstantne članice
Konstantne funkcije članice Da bi kompajler omogućio poziv
funkcije članice za konstantne objekte funkcija članica takođe mora biti definisana kao konstantna. (Ovo važi i za get funkcije!)
Funkcija članica se proglašava konstantnom tako što se (i u prototipu i u definiciji funkcije) iza liste parametara navede const.
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; }
Ako se za datu klasu neće definisati konstantni objekti, funkcije članice ne moraju da se definišu kao konstantne.
Ako se za neku klasu i definiše konstantan objekat, ali se za taj objekat neće pozivati funkcije članice, ni tada funkcije članice ne moraju da se definišu kao konstantne.
Za konstruktore i destruktore ne može da se koristi const!
Iz konstruktora je dozvoljeno i moguće pozivati funkcije članice koje nisu konstantne.
Konstantni objekti i konstantne članice
Primjer:#include <iostream>#include <cmath>#define K(a,b) pow(((a)-(b)),2)using namespace std;
class Tacka{ public: Tacka (double=0, double=0); double getX() const; double getY() const; double daljina(Tacka) const; void pisiTacka() const; private: double x, y;};
Tacka::Tacka(double xx, double yy) { x = xx; y = yy; }
double Tacka::getX() const { return x; }
double Tacka::getY() const { return y; }
double Tacka::daljina(Tacka t) const { return sqrt(K(x,t.x)+K(y,t.y)); }
void Tacka::pisiTacka() const { cout << "("<<x<<","<<y<<")"; }
int main(){ Tacka tA(3,4); const Tacka tO; // konstantan objekat
cout<<"A: "<<tA.getX()<<","<<tA.getY()<<endl;
cout<<"O: "<<tO.getX()<<","<<tO.getY()<<endl;
cout<<"A: "; tA.pisiTacka(); cout<<endl;
cout<<"O: "; tO.pisiTacka(); cout<<endl;
cout << "Udaljenost od A"; tA.pisiTacka(); cout << " do O"; tO.pisiTacka(); cout << " iznosi: " << tA.daljina(tO) << endl;
cout << "Udaljenost od O"; tO.pisiTacka(); cout << " do A"; tA.pisiTacka(); cout << " iznosi: " << tO.daljina(tA) << endl;}
A: 3,4O: 0,0A: (3,4)O: (0,0)Udaljenost od A(3,4) do O(0,0) iznosi: 5Udaljenost od O(0,0) do A(3,4) iznosi: 5
Konstantni objekti i konstantne članice
Konstantni podaci članovi Klasa može da sadrži i
konstantne podatke članove. Tada će kreirani objekti imati konstantne atribute.
Inicijalizacija konstantnih atributa ne može da se vrši u tijelu konstruktora korišćenjem operatora dodjele, već pomoću 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 takođe može da se vrši na isti način.
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; };
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(); }}
Prije petlje : stanje=10, korak=5stanje=15, korak=5stanje=20, korak=5stanje=25, korak=5
Pokazivač this
Osim formalnih argumenata, funkcije članice imaju i jedan “skriveni” argument (skriveni – ne vidi se u prototipu).
Taj “skriveni” argument je tekući objekat – objekat za koji je pozvana funkcija članica.
Adresa skrivenog argumenta (tekućeg objekta), za vrijeme izvršavanja funkcije članice, nalazi se u pokazivaču this.
Svaki objekat ima pristup svojoj vlastitoj adresi preko pokazivača this.
Pokazivač this koristi se implicitno za referenciranje članica i ne mora da se navodi (kao u dosadašnjim primjerima).
Pokazivač this može da se koristi i eksplicitno! Ako je tekući objekat vrijednost koju vraća data funkcija članica, Ako je tekući objekat argument neke funkcije, Za kaskadno pozivanje funkcija.
Pokazivač this
Primjer:#include <iostream>using namespace std;class Test { public: Test(int a=0) { x=a; }; 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); }
x = 12this->x = 12(*this).x = 12arg x = 100clan x = 12
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:05Novo vrijeme : 20:30
Pokazivač thisPrimjer:#include <iostream>#include <cmath>using namespace std;
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();}
a=1+i |a|=1.41421b=2 |b|=2c=i |c|=1d=3-4i |d|=5
Kompozicija: OBJEKAT kao ATRIBUT
Podatak član u nekoj klasi može da bude objekat (instanca neke klase). Kad neki objekat ima neki drugi objekat kao atribut, govorimo o
kompoziciji. Objekat može da sadrži jedan ili više objekata drugih klasa (automobil
ima točkove, sjedišta, volan, ...), tj. klasa može da sadrži više 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 može da postoji ako nema objekata koji je čine. Zato se prilikom kreiranja nekog složenog objekta (kompozicija), prvo kreiraju svi podobjekti, a zatim objekat koji ih sadrži (host objekat).
Prvo se pozivaju i izvršavaju 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 objekta.
Kompozicija: OBJEKAT kao ATRIBUT
Primjer:#include <iostream>using namespace std;class X { public: X(int i=0) : x(i) { cout << "X"; } int getX() { return x; } private: int x;};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(); }
YXAObjekat klase A sadrzi: podobjekat klase X: 1 podobjekat klase Y: 2 podatak tipa int: 3
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;} ~Datum() { cout<<"Dest. datuma: "; print(); } private: int dd, mm, gg; int provjeriDan(int dan) { static const int m[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; if (dan>0 && dan<=m[mm]) return dan; if (mm==2 && dan==29 && (gg%400==0 || (gg%4==0 && gg%100!=0))) return dan; return 1; }};
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();}
Kon. datuma: 28.2.1975.Kon. osobe : MarkoKon. datuma: 29.2.2000.Kon. osobe : JankoKon. datuma: 1.2.1900.Kon. osobe : SlavkoMarko je rodjen: 28.2.1975.Janko je rodjen: 29.2.2000.Slavko je rodjen: 1.2.1900.Dest. osobe : SlavkoDest. datuma: 1.2.1900.Dest. osobe : JankoDest. datuma: 29.2.2000.Dest. osobe : MarkoDest. datuma: 28.2.1975.
Statički (zajednički) članovi klase
Prilikom definisanja klase, članice mogu da se proglase statičkim (kvalifikator static ispred članice).
Statički član klase je zajednički za sve objekte date klase koji su stvoreni tokom izvršavanja programa.
Članice klase koje nisu zajedničke, nazivaju se pojedinačne članice klase.
I podaci i funkcije članice mogu biti zajednički članovi klase.
Zajednički podaci članovi Ako je podatak član zajednički član
klase, to znači da postoji samo jedan primjerak tog atributa, bez obzira na broj objekata.
Pristup zajedničkom atributu je pristup istoj memorijskoj lokaciji za sve objekte.
Mijenjanjem vrijednosti zajedničkog atributa utiče 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;
Statički (zajednički) članovi klase
Primjer:
#include <iostream>using namespace std;class Komuna { public: Komuna(char c) : naziv(c) { cout << ++brojac << ". objekat zove se: " << naziv << endl; } private: static int brojac; // ZP char naziv; // PP};int Komuna::brojac = 0; // inicijalizacija ZPint main() { Komuna a('A'), b('B'), c('C'); }
1. objekat zove se: A2. objekat zove se: B3. objekat zove se: C
Statički (zajednički) članovi klase
Zajedničke funkcije članice Zajedničke funkcije članice ne
posjeduju pokazivač this. Zajedničke funkcije članice
pristupaju zajedničkom atributu direktnim referenciranjem atributa.
Primjer:class Klasa { static int a; public: static int f() { cout << ++a; }};int Klasa::a=0;
Zajedničke funkcije članice pristupaju pojedinačnom 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; }};
Pojedinačne funkcije članice mogu direktno da pristupe i pojedinačnim i zajedničkim atributima.
Statički (zajednički) č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 ZPint Klasa::f(){ int i=a; // ZF moze da pristupi ZP int j=b; // ERR - ZF ne moze da pristupi PP return i+j;}void Klasa::g(Klasa x, Klasa *y, Klasa &z){ int i = x.b; // ZF moze da pristupi int j = y->b; // PP konkretnih objekata z.b = i + j; }int Klasa::h( int x ) // PF moze da { return (a+b)*x; } // pristupa i PP i ZP
int main(){ // poziv ZF bez konkretnog objekta int p=Klasa::f(); // ERR - poziv PF ne moze bez objekta int q=Klasa::h(5); Klasa k; Klasa::g(k,&k,k); // poziv ZF int s=k.h(6); // poziv PF}