Upload
fionn
View
51
Download
0
Embed Size (px)
DESCRIPTION
Ra čunarski praktikum 1 Vježbe 7. Zvonimir Bujanović Vinko Petričević. Ugnje žđene strukture. strukture mogu sadržavati i druge strukture. struct stogStringova { ... }; struct A utomobil { string registracija; stogStringova vlasnici; int godina P roizvodnje; } ;. - PowerPoint PPT Presentation
Citation preview
Računarski praktikum 1Vježbe 7
Zvonimir Bujanović
Vinko Petričević
Ugnježđene strukture
strukture mogu sadržavati i druge strukture
struct stogStringova { ...};
struct Automobil{ string registracija; stogStringova vlasnici; int godinaProizvodnje;};
Ugnježđene strukture: konstruktor
ako neki element strukture nema defaultni konstruktor (bez parametara), potrebno ga je navesti u konstruktoru strukture
struct stogStringova { stogStringova(int velicina) ...};
struct Automobil { stogStringova vlasnici; Automobil() : vlasnici(5) {...} Automobil(int maxVl):vlasnici(maxVl){} };
Ugnježđene strukture: drugi pristup
ponekad struktura članica ima smisla samo unutar veće strukturestruct Automobil { struct Motor { int snaga; double obujam; Motor (int s, double o) { snaga = s; obujam = o; } };
Motor m; int brojVrata; Automobil() : m(90, 1.4) { ... } Automobil(int s, double o) : m(s, o) { ... }};
Ugnježđene strukture: drugi pristup
možemo svejedno deklarirati i varijable tipa Motor:Automobil yugo(45, 1.2);Motor tdi(120, 1.9); // krivo!Automobil::Motor turboDiesel(120, 1.9); // OKyugo.m = turboDiesel;
cout << yugo.m.snaga;cout << yugo.brojVrata;
Zadatak 1 Napravite implementaciju atp-a list pomoću polja; lista treba moći
čuvati max. 100 elemenata proizvoljnog tipa Struktura treba sadržavati i tip podatka iterator tako da se može
raditi sljedeće:
uputa: neka iterator sadrži pokazivač na tip
list<int> L;L.push_back(5); L.push_back(7);
list<int>::iterator li = L.begin();while (!li.isEqual(L.end())){ cout << li.data() << “ “; li = li.next();}
const varijable
svaki tip podatka koji smo do sada susretali, može biti i const-tip (njegov sadržaj je moguće samo čitati).
const varijable se moraju inicijalizirati:
konverzija s “normalnog” u const tip je moguća, ali obrnuta ne:
const int a; // krivo!const int b = 5; // OK
const int a = 5; int b = 3;a = b; // krivo!b = a; // OK
const pointeri
u deklaraciji
konstantno je ono na što pokazuje s, a ne i sama varijabla s. Dakle:
const char *s = “rp1”;
char *s1 = “abc”; const char *s = “rp1”;
s[1] = ‘A’; // greska, mijenjam ono na sto pok. ss1 = s; // greska,preko s1 bi se mogao mijenjati s!s = s1; // OKs[1] = ‘A’; // i dalje greskas1[1] = ‘A’; // OK
const varijable
const nam koristi da zabranimo izmjenu nekih stvari u strukturama koje kreiramo
Npr. string::c_str() vraća const char *
slično: operator* na set<T>::iterator vraća const T, budući da bi mijenjanje vrijednosti uništilo uređenje strukture
void ispis(char *s) {...}void ispis1(const char *s) {...}string s;ispis(s.c_str()); // greškaispis1(s.c_str()); // OK
const funkcije članice
Funkcije članice koje ne modificiraju objekt moguće je deklarirati kao const funkcije (u tom slučaju ih je onda moguće pozivati i na const objektima) struct MyString{ char *data; int duljina; MyString() { ... } MyString(const char *s) { ... } int length() const { ... } const char *c_str() const { ... }};const MyString s; // ok, init je konstruktor!int i=s.length(); // OK jer je i length const
Reference
ako funkcija treba promijeniti varijablu koju joj šaljemo kao parametar, onda u C-u tu varijablu treba slati kao pointer:void f ( int *p ) { *p = 3; }
int main() { int x = 5; f(&x); cout << x; // ispisuje 3 return 0;}
Reference
u C++-u osim pointera i “običnih varijabli” postoje i reference – to su varijable koje se ponašaju kao pointeri, a s njima radimo kao sa “običnim varijablama” (bez * i &)
referenca uvijek mora biti inicijalizirana:
int a=5, b=3;int &r = a; // OK, r je referenca na aint &t = 5; // krivo! nema varijableint &s; // krivo! nema varijable
cout << r; // ispisuje 5r = b; // u r(tj. u a) napisi vrijednost od bcout << r << “ “ << a; // ispisuje 3 3
Reference
reference se ponašaju kao pointeri:int a=5;int &r = a;
cout << a; // ispisuje 5r = 7; cout << a; // ispisuje 7
void f (int &a) { a = 7; }
int main() { int x = 5; f(x); cout << x; // ispisuje 7}
Reference
const reference – ne može se mijenjati ono na što referiraju:
funkcijama se često šalje const referenca. Zašto? zašto copy-konstruktor prima referencu, a ne
“običnu varijablu” i zašto je ta referenca const?
int a=5;const int &r = a;
cout << r; // ispisuje 5r = 7; // krivo! r je const referencaa = 7; // ok, a nije const varijablacout << r; // ispisuje 7
Reference funkcija može vraćati referencu:
što bi se dogodilo da funkcija nije primila referencu, već “običnu varijablu”?
int &prviElementVektora(vector<int> &V){ return V[0]; }
int main () { vector<int> V(10);
cout << V[0]; // ispise 0 prviElementVektora(V) = 5; // OK!!! cout << V[0]; // ispise 5}
Reference
oprez: ne smijemo vraćati referencu na lokalnu varijablu u funkciji!
int &proba(int *a){ int temp = 5; *a = 5; return temp; // krivo (warning), temp je lok.! return *a; // ok, a živi i van proba}
int main () { int x = 3; int y = proba(&x); // OK, y = 5; int &t = proba(&x); // OK t++; cout << x; // ispise 6}
this pointer
kad pozivamo funkciju članicu, kako funkcija “zna” sa kojim smo je objektom pozvali?
odgovor: implicitno se funkciji zapravo šalje adresa objekta koji ju poziva
stack S, T;S.push(5); T.push(5);
stack S, T;push(&S, 5);push(&T, 5);
struct stack { ... void push(int x);};
void push (stack *S, int x){ S->podaci[S->vrh++] = x; }
this pointer
unutar svake funkcije članice postoji varijabla this koja sadrži adresu od objekta koji je pozvao funkciju
struct stack { void push( int x ) { this->podaci[this->vrh] = x; this->vrh++; }};
this pointer
na ovaj način moguće je vratiti referencu na sam objekt, što je ponekad korisnostruct stack { stack &push( int x ) { podaci[vrh++] = x; return *this; }};
int main () { stack S; S.push(5).push(7).push(8); // OK!}
static varijable
Statički podaci su smješteni u kôdu (kao i globalne varijable), i inicijaliziraju se samo jednomvoid f() { static int i=0; cout << ++i;}void f1() { static int i=0; cout << ++i;}...f(); // ispiše 1f(); // ispiše 2f1(); // ispiše 1f1(); // ispiše 2
static varijable
Kreiraju se prilikom prvog korištenja, a uništavaju (ako su bile kreirane) na kraju izvršavanja programa.struct S { S() { cout << “Kreiran S” << endl; } ~S() { cout << “Unisten S” << endl; }};void f() { static S s;}int main() { cout << “Poceo program” << endl; f(); cout << “Zavrsio program” << endl; return 0;}
static elementi strukture
zajednički su za sve objekte nekog tipa ne zauzimaju memoriju na heapu/stacku moraju biti ‘inicijalizirani’ izvan svih funkcija
struct MyStruct { static int brojZivihStruktura; MyStruct() { brojZivihStruktura++; } ~MyStruct() { brojZivihStruktura--; }};
int MyStruct::brojZivihStruktura = 0;
int main() { MyStruct a, b, c;cout << MyStruct::brojZivihStruktura; return 0; }
Zadatak 2
Nadopunite definiciju strukture sa prethodnog slide-a tako da osim broja trenutno živih objekata tipa MyStruct ona održava i popis (listu) svih tih objekata
uoči: popis mora sadržavati pointere ili reference. Što bi se dogodilo da se u popisu nalaze samo MyStruct-ovi?
static funkcije članice
static funkcije mogu pristupati samo static članovima strukture (nemaju this)
možemo ih pozivati i direktno (bez varijable)
struct MyStruct{ static int brojStruktura; int brojac; MyStruct() { brojac = brojStruktura++; } static int broj() { return brojac; // greska, brojac nije static return brojStruktura; // OK }};
int i = MyStruct::broj(); // MyStruct s; int i=s.broj();
extern
Ako istu varijablu koristimo u više .cpp datoteka (koje zajedno linkamo), trebamo navesti da je ona extern.// neki.hextern int zajednicka_varijabla;
// u samo jednom .cppuint zajednicka_varijabla;
Pretpostavljeni parametri funkcija
Svi ili nekoliko zadnjih parametara funkcije mogu imati postavljene defaultne vrijednosti
void f(int a, string b=“netko”) { cout <<b<<“ ima “<<a<<“godina”;}
int main () { f(20, “Mirko”); // Mirko ima 20 godina f(19); // netko ima 19 godina}
Pretpostavljeni parametri funkcija
oprez, lako može doći do dvosmislenosti!
struct MyStruct { MyStruct() { ... } MyStruct(int a=5) { ... }};
MyStruct a; // krivo: koji konstruktor?MyStruct b(7); // OK