[OOUP] Gradivo
Marko
Kako ste nacrtali graf ovisnosti u mi2017 zadatak 4?
cloudies
Prof Možda ako ti ove moje bilješke s auditornih nešto znače
nikace
- zad MI19
Neke bilješke s konzultacija (ako vidite neke krive info ispravite me plizz):
Što se sve uočava analizom strojnog koda?
Iz strojnog koda razreda Identity vidimo da poziva konstruktor razreda Unary_Function (zaključujemo da Identity nasljeđuje Unary_Function)
Unary_Function u sebi sadrži virtualne metode, a ispod prvog poziva operatora new u strojnom kodu uočavamo poziv nevirtualne metode (redak 8) -> zaključujemo da se u metodi main prvo stvara primjerak razreda Square (koji nema virtualne metode).
Instrukciji call na neki način trebamo prenijeti argumente. Argumenti mogu biti preneseni samo preako registara i taj argument ide preko registra ‘edi’. Za prvi poziv operatora new taj argument je 1, a za drugi 8.
Zašto se šalje 1, a zašto 8?
Razred uvijek uzme 1 bajt kada nema nikakvih podatkovnih članove. Takav je slučaj razred Square. A za Identity se alocira 8 bajtova. Također može se uočiti da je strojni kod pisan za 64bitnu arhitekturu, to se vidi po tome što se za pointer zauzima 8 bajtova.
(a)
Argument je ebroj bajtova koje treba zauzeti, a povratna vrijednost je pokazivač na taj memorijski prostor.
(b)
prvo je razred Square, zatim Identity : public Unary_Function
u mainu se prvo stvara Square f1 = new Square(), a zatim Unary_Function (ili Identity) f2 = new Identity()
©
Metoda ima jedan argument, ali funkcijski poziv metode onda treba imati dva arugmenta (skriveni argument = this, int). Taj this se prenosi u registru rdi.
(d)
6 u rax je ono što vrati operator new (pokazivač na objekt nad kojim se poziva metoda -> f1)
17 u rax se sprema pokazivač na objekt identity -> f2
18 u rax se nalazi adresa prvog člana objekta f2, a to je pokazivač na virtualnu tablicu
19 zbog toga što za pointer treba 8 bajtova, povećanjem za 8 bajtova pomičemo se na drugi član virutalne tablice a to je adresa metode neg_value_at
20 rax sada pokazuje na funkciju neg_value_at razreda Unary_Function (jer je Identity nije implementirala)
(e)
main 19 strojni kod 2-4 (alocira se mjesto za objekt; ne pozove se konstruktor zato što taj konstruktor nije zadan u kodu; novi objekt se spremi na rbp-24 adresu)
main 20 strojni kod 5-8 (lokalna varijabla se povuče u rax= this; 5 se spremi u esi; rax se spremi u rdi, pozove se metoda)
main 21 strojni kod 9-15 (ovdje nije samo da se alocira memorija, već se i poziva konstruktor; 15ti redak pohranjuje novi objekt u lokalnu varijablu)
main 22 strojni kod 16-23 (21.redak 3 se sprema u esi)
(f)
trik pitanje = taj konstruktor se ne poziva
To znači da ga nema, a to znači da nije potreban -> ne treba naštimavati pokazivač na virtualnu tablicu.
(g)
Square ima potpuno isto sučelje kao Unary_Function -> Square bi trebao naslijediti Unary_Function
Može li netko možda objasniti onaj zadatak s labosa? Unaprijed hvala 😀
Me1
može neko podijelit rješenja od ostalih ispita ako je rješavao
fer999
Može li netko tko ima screenshotove rješenja MI s konzultacija objaviti tu sve?
[obrisani korisnik]
M̵̧̩͑̀͝î̶͍̉ć̴̝̾́̀o̶̺̟̣͂̽
U kojem smislu gola strategija? Dijagram razreda se cini mrvicu kompleksniji od strategija,
micho
[obrisani korisnik] Dijagram razreda se cini mrvicu kompleksniji od strategija,
Hence zašto su dijagrami razreda (((njihov))) trik
faboche
Kako znamo hoćemo li u dijagramu koristiti agregaciju ili obicno referenciranje?
indythedog
him Okej, objasniti ću na primjeru iz MI-2019, 3. zadatak.
Vidimo da nam npr. klasa Svemirski brod ima agregaciju prema klasi Potisnik. To je zato što u zadatku kaže da svaki svemirski brod ima najmanje jedan potisnik.
S druge strane, klasa Teretni (brod) referencira klasu Vozilo, jer u zadatku kaže da svaki teretni brod može prevoziti više vozila.
Okej, zašto je jedno onda referenca, a drugo agregacija? Zato što agregaciju koristimo kad želimo naznačiti da je objekt koji se agregira - u ovom primjeru potisnik, dio agregatora (svemirskog broda). S druge strane, kad teretni brod prevozi druga vozila, ona nisu njegov ključni dio, nego ih on samo prevozi, pa eto mora imati referencu na njih da zna koja točno vozila prevozi.
Slično i u ovom primjeru s prezentacije:
znamo da su gume jedna od komponenata od kojih se kamion sastoji, pa to označavamo agregacijom.
Šegvić je još na konzultacijama dodao da je razlika i u tome što kod agregacije, objekt koji se agregira (potisnik) ne može postojati bez roditeljskog objekta (svemirskog broda), odnosno da to ne bi imalo smisla. Ja se baš ne slažem s tim, jer iako u ovom primjeru to ima smisla, ako pogledamo prezentaciju o OO Dekorator:
vidimo da je označeno da dekorator agregira component. Istina je da je component ključni dio dekoratora, no meni nema niakakvog smisla da component ne može postojati bez dekoratora. Rekao bi da je ovo na što je Šegvić mislio kompozicija, a ne agregacija. Možda sam u krivu, no u svakom slučaju ja bi se samo držao definicije da agregaciju koristimo kad želimo naznačiti da se klasa A (agregat) sastoji od nekih instanci klase B, i to bi trebalo biti točno.
zastozato
može li netko objasniti rješenje iz 1. blica zadatak sa strojnim kodom?
Rene
studoš Evo objašnjenje liniju po liniju:
mov rdi, QWORD PTR -8[rbp]
u registar rdi dohvati prvi argument funkcijskog poziva.
call _ZN4BaseC2Ev
pozovi konstruktor razreda Base.
Zaključuješ da Base ima konstruktor koji ima samo jedan argument, a pošto mora imati skriveni argument this, to je onda i jedini argument.
lea rdx, _ZTV6Client
dohvati adresu virtualne tablice za razred Client u registar rdx (hint: LEA = Load Effective Address)
mov rax, QWORD PTR -8[rbp]
- u rax stavi prvi argument, za koji smo zaključili da je skriveni argument this
mov QWORD PTR[rax], rdx
- tamo gdje pokazuje rax upiši sadržaj registra rdx u kojemu smo spremili adresu virtualne tablice. Ovime si postavio pokazivač na VTABLE na prvo mjesto u objektu.
mov rax, QWORD PTR -16[rbp]
stavi drugi argument funkcijskog poziva u rax
mov rax, QWORD PTR[rax]
dereferenciraj rax.
Ovdje zaključuješ da je drugi argument pokazivač na neki objekt. Prvo u rax staviš taj pokazivač, onda ga dereferenciraš i sad je u rax prvi član tog objekta, tj. pokazivač na virtualnu tablicu.
mov rdx, QWORD PTR[rax]
u rdx stavljaš ono na što pokazuje rax - sada je to pokazivač na prvu funkciju virtualne tablice.
mov rdi, QWORD PTR -16[rbp]
- drugi argument funkcije, onaj objekt čiju si virtualnu tablicu upravo dohvatio, stavljaš u rdi
call rdx
pozovi funkciju čiji se pokazivač nalazi u rdx.
Iz svega ovoga zaključuješ:
Pozvao si konstruktor od Base, a dobivenom objektu postavio virtualnu tablicu od razreda Client dakle Client nasljeđuje Base. Konstruktor Clienta prima dva argumenta, skriveni this i pokazivač na neki objekt koji ima virtualnu metodu, u službenom rješenju to je Worker. Virtualna metoda tog razreda prima samo jedan argument, skriveni this.
I iz toga složiš onakvo rješenje u C++ ili nešto slično.
flicka
moze neko objasnit dijagram iz 2. zad, iz mi19 rjesavanog na konzultacijama
faboche
indythedog Hvala puno na pojasnjenju. Ima mi smisla.
indythedog Šegvić je još na konzultacijama dodao da je razlika i u tome što kod agregacije, objekt koji se agregira (potisnik) ne može postojati bez roditeljskog objekta
Sjecam se tog dijela, mislim da se zbunio i da je mislio na kompoziciju.
steker
Moze neko rjesit ovo(2017 mi)
fer999
ima li netko rješen 4. zadatak iz MI 2018/2019?