Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

vTable / polimorfizam

[es] :: .NET :: vTable / polimorfizam

[ Pregleda: 2092 | Odgovora: 7 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon vTable / polimorfizam23.07.2006. u 13:19 - pre 215 meseci
Primetio sam da se dosta ljudi ne snalazi bas sa konceptom polimorfizma i da je neko cak i trazio objasnjenje kako radi vTable, pa ajd da pokusam da razjasnim.

1. Sta je vTable?

vTable je u najosnovnijem obliku niz "funkcijskih" pointera. Sa tom razlikom sto svaki od tih pointera ne pokazuje na neki podatak vec na kod odredjenog metoda. Prva greska koju ljudi prave je da vTable direktno asociraju sa OOP-om. Iako OOP ne moze funkcionisati bez vTable-a, nista vas ne sprecava da u C-u napravite niz function pointera, popunite tu listu i onda radite "indirektne" pozive preko tog niza (http://www.codeproject.com/cpp/PolyC.asp), mada se to naravno ne radi u praksi

2. Sta omogucava vTable?

Omogucava dve veoma vazne OOP tehnologije, polimorfizam i interfejse.

3. Kako to ustvari radi?

Ok, uzmimo ovo parce koda (C#):

Code:

    public class Deda 
    {
        public int polje1;
    
        public static void Staticki() {}
        public virtual void Metod() {}
        public virtual void Metod(int par) {}
        public void Obicni() {}
    }

    class Class1
    {
        [STAThread]
        static void Main(string[] args)
        {
            Deda d = new Deda();
            Deda.Staticki();
            d.polje1 = 123;
            d.Metod();
            d.Metod(1234);
            d.Obicni();
        }
    }


Prilicno jednostavna klasa, jedno polje, jedan staticki metod, dva virtuelna overloaded metoda i jedan obicni metod. U Class1 instanciramo tu klasu i pozivamo sve sto treba.

C# za razliku od C++-e ne pravi native code, pa se necu zadrzavati mnogo na MSIL-u vec cemo tretirati kao da je sve to vec stiglo do native koda.

Kompajler, kad bilduje klasu, ima nekoliko aspekata.
Sva polja idu direktno u memorijski potpis klase. Staticke metode i obicne metode se linkuju staticki na ulaz u odgovarajuci kod metoda (jedina razlika izmedju statickih i obicnih metoda je da se statickom ne prosledjuje skrivena referenca na objekat ciji metod se poziva), vTable nema nikakav uticaj ovde.

E sad, za svaki virtual metod (i virtuelne property accessore), alocira se slot u vTable i u tu poziciju se "upuca" pointer na kod metoda. vTable se alocira van objekta na pocetku aplikcije i svaka klasa koja ima bar jedan virtuelni metod ima svoj vTable koji koriste svi objekti te klase. Na kraju, memorijski potpis ove klase izgleda ovako (bar u skolskom primeru, vise o tome posle):

Code:

Instanca klase (iliti objekat)                vTable za Deda (samo jedan za celu aplikaciju)
+------------------------------+              +--------------------------------+
| Pointer na vTable            |  --------->  | [0] pointer na Deda.Metod()    |
| polje1                       |              | [1] pointer na Deda.Metod(int) |
+------------------------------+              +--------------------------------+



Sta se desava pri pozivanju? Ovako izgleda MSIL kod u Class1

Code:


      .locals init (
            [0] ConsoleApplication1.Deda deda1)

      // Deda d = new Deda();
      L_0000: newobj instance void ConsoleApplication1.Deda::.ctor()
      L_0005: stloc.0 

      // Deda.Staticki()
      L_0006: call void ConsoleApplication1.Deda::Staticki()

      // d.polje1 = 123
      L_000b: ldloc.0 
      L_000c: ldc.i4.s 123
      L_000e: stfld int32 ConsoleApplication1.Deda::polje1

      // d.Metod()
      L_0013: ldloc.0 
      L_0014: callvirt instance void ConsoleApplication1.Deda::Metod()

      // d.Metod(1234);
      L_0019: ldloc.0 
      L_001a: ldc.i4 1234
      L_001f: callvirt instance void ConsoleApplication1.Deda::Metod(int32)

      // d.Obicni();
      L_0024: ldloc.0 
      L_0025: callvirt instance void ConsoleApplication1.Deda::Obicni()



Prva stvar koja bode oci je d.Obicni(). Ako to nije virtuelni metod, zasto se koristi callvirt? Razlog je u tome sto sam C# kompajler uopste i ni na koji nacin ne radi sa vTable , c# kompajler samo daje odgovarajuce instrukcije u MSILu (ako je staticki metod onda call, ako je objektni onda callvirt) da bi JIT kompajler mogao da odradi konverziju u native kod i naposletku samo linkovanje koje nam je poznato iz C++-a, dakle JIT je taj koji bilduje i kreira vTable. Ovako izgleda finalni native kod:

Code:

    class Class1
    {
        [STAThread]
        static void Main(string[] args)
        {
            Deda d = new Deda();
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  sub         esp,8 
00000006  push        edi  
00000007  push        esi  
00000008  mov         dword ptr [ebp-4],ecx 
0000000b  xor         esi,esi 
0000000d  mov         ecx,9D5140h 
00000012  call        F9B21FC0 
00000017  mov         edi,eax 
00000019  mov         ecx,edi 
0000001b  call        dword ptr ds:[009D5188h] 
00000021  mov         esi,edi 

            Deda.Staticki();
00000023  call        dword ptr ds:[009D5180h] 

            d.polje1 = 123;
00000029  mov         dword ptr [esi+4],7Bh 

            d.Metod();
00000030  mov         ecx,esi 
00000032  mov         eax,dword ptr [ecx] 
00000034  call        dword ptr [eax+38h] 

            d.Metod(1234);
00000037  mov         ecx,esi 
00000039  mov         edx,4D2h 
0000003e  mov         eax,dword ptr [ecx] 
00000040  call        dword ptr [eax+3Ch] 

            d.Obicni();
00000043  mov         ecx,esi 
00000045  cmp         dword ptr [ecx],ecx 
00000047  call        dword ptr ds:[009D5184h] 
        }
0000004d  nop              
0000004e  pop         esi  
0000004f  pop         edi  
00000050  mov         esp,ebp 
00000052  pop         ebp  
00000053  ret              


Pa ajd da krenemo redom. Prva linija je pozivanje konstruktora i smestanje reference u lokaciju 0, na asmeblerskom delu se vide dva poziva, prvi je nevazan za pricu (alokacija), drugi je poziv konstruktora i smestanje reference u ESI registar (koji u stvari predstavlja MSILovu lokaciju 0).

Deda.Staticki();
MSIL koristi call konstrukciju, JIT koristi indirektan poziv (za one slabije sa asemblerom, call je direktan poziv na fisknu adresu unutar istog code segmenta, call dword ptr je indirektni poziv, tj, idi na adresu u operandu, uzmi adresu metoda i pozovi tu adresu)
Sada iskace pitanje, ako smo rekli da je u pitanju staticki poziv i ako znamo da JIT definitivno zna adresu na koju je smestio Staticki(), zasto se u asembleru koristi indirektni poziv (call dword ptr) a ne staticki poziv?
To pitanje je na mestu i odgovor malo kasnije, ali posledica trenutne implementacije JIT-a je da nikad (ali nikad) ne koristi staticke pozive za MSIL kod. Iako delimicno smanjuje performanse programa ovo nema toliko znacaja u funkcionisanju koliko ima u kasnijoj raspravi o early/late binding, al otom potom.

d.polje1 = 123;
MSIL ucitava lokaciju 0 (referenca na d), ucitava kosntantu 123 i koristi stfld da upuca vrednost u polje1. JIT to prevodi u indirektni mov (mov dword ptr). ESI nosi adresu reference, na 4 bajta udaljenosti od pocetka nalazi se memorijska lokacija polje1 i u nju upucava konstantu 7Bh (123). Ako pogeldate dijagram sa pocetka, na adresu ESI se nalazi objekat, na lokaciji ESI+0 je pointer na vTable, te je na lokaciji ESI+4 locirano polje1.

d.Metod();
ok, poziv virtuelnog metoda. MSIL ucitava lokaciju 0 (referencu kao skriveni parametar za metod) i poziva Metod() sa callvirt. JIT na osnovu metadata zakljucuje da je poziv virtuelnog metoda i koristi vTable.
Ovako, na adresi ESI+0 je pointer na vTable, pa je proces sledeci:
- mov ecx, esi - kopira referencu na objekat u exc (skriveni parametar)
- mov eax, eax,dword ptr [ecx] - kopira u eax cetiri bajta sa lokacije ecx+0 (tj esi+0), tj pointer na pocetak vTable. U ovom trenutku eax (navodno) pokazuje na vTable.
- call dword ptr [eax+38h] - ovo je pravi indirektni vTable-driven polimorficki poziv. . JIT zna da je na lokaciji 38h unutar vTable-a adresa metoda Metod(), procesor ucitava tu adresu i poziva metod.

d.Metod(1234);
Slicno kao gore, samo sto EDX nosi neskriveni parametar 1234. Takodje, vidi se da je lokacija u vTable sada +3Ch (sledeca lokacija u vTable)

d.Obicni();
Slicno kao Staticki(), poziva se indirektni metod, samo sto se pre poziva u ecx ubacije referenca (skriveni parametar), sto je jedina razlika izmedju pozivanja statickog i objektnog metoda.



4. Nasledjivanje...

ako dodamo sledecu klasu
Code:

    public class Unuk: Deda
    {
        public override void Metod() {}
    }

    class Class1
    {
        [STAThread]
        static void Main(string[] args)
        {
            Deda d = new Deda();
            Deda u = new Unuk();
            d.Metod();
            u.Metod();
        }
    }


Preskocicemo MSIL i dati samo asm:
Code:

            Deda d = new Deda();
00000010  mov         ecx,9D5140h 
00000015  call        F9B21FC0 
0000001a  mov         esi,eax 
0000001c  mov         ecx,esi 
0000001e  call        dword ptr ds:[009D5188h] 
00000024  mov         edi,esi 

            Deda u = new Unuk();
00000026  mov         ecx,9D51C8h 
0000002b  call        F9B21FC0 
00000030  mov         esi,eax 
00000032  mov         ecx,esi 
00000034  call        dword ptr ds:[009D5208h] 
0000003a  mov         ebx,esi 

            d.Metod();
0000003c  mov         ecx,edi 
0000003e  mov         eax,dword ptr [ecx] 
00000040  call        dword ptr [eax+38h] 

            u.Metod();
00000043  mov         ecx,ebx 
00000045  mov         eax,dword ptr [ecx] 
00000047  call        dword ptr [eax+38h] 


Iz ovog se vidi da su dva poziva identicna (call dword ptr [eax+38h]), ali opet d.Metod() poziva Deda.Metod, a u.Metod poziva Unuk.Metod() iako su i u i d istog tipa (Deda).

"Tajna" je u vTable-u. U ovom primeru edi nosi referencu na d, a ebx nosi referencu na u. Jedina razlika je ta sto se na adresama edi+0 nalazi vTable za Deda klasu (u ovom primeru 9D5140h), a na ebx+0 adresa za vTable klase Unuk (9D51C8h), u te dve tabele na lokaciji 38h nalaze se dva razlicita funkcijska pointera, i to je nacin na koji vTable omogucava polimorfizam, bez obzira na to koji je tip reference, odluku o tome koji metod se poziva donosi odgovarajuca lokacija u vTable.


5. Kako to .NET radi za razliku od C++-a...

Ono sto mozda zapadne za oko je pitanje: ako Klasa Deda ima samo dva virtuelna metoda, zasto su funkcijski pointeri na lokacijama 34h i 38h a ne 0h i 4h?

Odgovor lezi u nacinu na koji JIT prevodi MSIL kod. Klasicni (C++) kompajler i linker, prevo prevede kod u prvom prolazu usput pamteci staticke lokacije metoda i lokacije sa kojih se poziva, onda linker na osnovu te tabele izbilda sve vTable-ove i upuca "staticke" lokacije u pozive.
JIT sa druge strane (verovatno zbog brzine prevodjenja) ima samo jedan prolaz kroz kompajler/linker. U takvom rezimu JIT kad prevodi poziv metoda ne zna gde se kod tog metoda nalazi pa da bi izbegao dvoprolaznost, ima mali korak na pocetku: za svaku klasu (iz metadata) JIT rezervise prostor za vTable koji sadrzi SVE metode, i staticke i obicne i virtuelne. Tako da iako u trenutku prevodjenja mozda ne zna gde ce se nalaziti npr. Deda.Staticki() ali ZNA da ce pointer na taj metod biti na lokaciji u vTable ciju adresu zna. I tako kako prolazi kroz metod po metod, generise native code i indirektne pozive drugih metoda i onda na kraju upuca entry-point u odgovarajucu lokaciju u vTable, bez potrebe da u drugom prolazu tu adresu stavi u sve pozive tog metoda, tako da vTabele za nase klase ustvari izgledaju ovako:

Code:

Instanca klase Deda                           vTable za Deda 
+------------------------------+              +--------------------------------+
| Pointer na vTable            |  --------->  | <rezervisano ili nevazno>      |
|                              |              | Deda.Staticki()                |
| polje1                       |              | Deda.Metod()                   |
+------------------------------+              | Deda.Metod(int)                |
                                              | Deda.Obicni()                  |
                                              +--------------------------------+

Instanca klase Unuk                           vTable za Unuk 
+------------------------------+              +--------------------------------+
| Pointer na vTable            |  --------->  | <rezervisano ili nevazno>      |
|                              |              | Deda.Staticki()                |
| polje1                       |              | Unuk.Metod()                   |
| polje2                       |              | Deda.Metod(int)                |
+------------------------------+              | Deda.Obicni()                  |
                                              +--------------------------------+


C++ programeri se u startu mrste na ovo zbog potpuno nepotrebnog gubitka memorije i u pravu su, nije bas idealno resenje sa stanovista optimizacije upotrebe memorije, i sa stanovista brzine pozivanja metoda, ali poprilicno ubrzava proces JIT kompajliranja.

6. Interfejsi

Interface je funkcionalno nista drugo do "ogoljena" referenca koja sadrzi samo pointer na vTable koji se nalazi unutar vTable klase koja ga implementira. Recimo da postoji Interface IDeda koji ima jedan metod (void Obicni()) i da klasa Deda implementira taj interface. vTable za IDeda ne pocinje na istoj lokaciji kao vTable za Deda klasu nego na lokaciji koja definise pointer na metod Obicni(). Naravno, ovo implicira da se svi metodi nekog interface-a u vTable klase koja ih sadrzi nalaze jedan iza drugog i tako je bilo bar do sada

Implementacija Interface-a na .NET JIT je komplikovana (konsultuju se tri tabele umesto jedne), pa cu tu pricu ostavitri za neki drugi put.


7. Early/Late binding

Kompjuterski naucnici definisu late binding kao poziv "necega" cija se adresa na zna do trenutka pozivanja. Po toj definiciji svi virtuelni metodi su late-bound (zato sto se adresa indirektno odredjuje iz vTable a pri kompajliranju se ne zna koji ce tacno vtable biti u referenci), dok su svi staticki i objektni metodi early-bound, i tako je bilo do skoro . Asemblerski receno, call je early-bound, [call dword ptr] je late bound.

Terenci (kao sto sam ja) uglavnom smatraju ovu definiciju zastarelom, narocito sa uvodjenjem .NET-a
Na osnovu prethodne diskusije vidi se da po toj definiciji uopste ne postoji early binding u .NETu posto su svi pozivi implementirani sa [call dword ptr]. Zabunu su pokusali da rese tvrdnjom da se definicija odnosi samo na sors code, ali je to uvelo jos vecu zabunu i otezalo odredjivanje sta je u stvari late a sta early binding, narocito za manje iskusne korisnike, a i efektivno cemu definicija ako nema neko utemeljenje u realnoj praksi, mozemo da se lazemo tri dana da je to early-binding kad je implementacija i early i late bound poziva ista

U celoj toj prici postoji i koncept dinamickog bindovanja kakav koristi COM gde se klasa dinamicki "ucitava" i onda konsultuje type-library da se locira ID metode i zatim pozivanje metoda obavlja kroz IDispatch interfejs (slican mehanizam za .NET postoji u refleksiji), i to je tehnika koja sa sobom vuce pad performansi, i koji se u VB terminlogiji tretira kao late binding, i sa kojim se i ja licno slazem.

Definicija koju ja prihvatam je da je early binding poziv nekog metoda cija adresa je poznata u trenutku prevodjenja ILI je prisutna u adresnom prostoru programa u trenutku poziva. Late bound su svi pozivi cija odredisna adresa mora da se "sracuna" prilikom pozivanja.





[Ovu poruku je menjao mmix dana 25.07.2006. u 12:31 GMT+1]
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

spartak

Član broj: 5625
Poruke: 631
*.ptt.yu.



+3 Profil

icon Re: vTable / polimorfizam23.07.2006. u 14:19 - pre 215 meseci
Kolega Mitrovicu sedite, 10+
 
Odgovor na temu

havramm
Miroslav Havram
Software Developer / Engineer
Beograd

Član broj: 4603
Poruke: 255
212.62.55.*



Profil

icon Re: vTable / polimorfizam23.07.2006. u 14:33 - pre 215 meseci
Za jos malo perverzija sa pointerima i "vTablama" - ATL Under the Hood - Part 1 (ima ih 5, pa ko voli...). Nema veza sa Frameworkom, ali je korisno znati - principi su isti...
If it's a girl then they're gonna call it Sigourney, after an actress. If it's a boy, then they're gonna call it Rodney, after Dave!
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: vTable / polimorfizam24.07.2006. u 11:57 - pre 215 meseci
Citat:
spartak: Kolega Mitrovicu sedite, 10+


Samo se vi zaje*avajte, sutra kontrolni

Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

Crtani
Dejan Savic
Beograd

Član broj: 95930
Poruke: 46
*.20.eunet.yu.

Sajt: www.klikeri.net


Profil

icon Re: vTable / polimorfizam24.07.2006. u 13:14 - pre 215 meseci
Najpre, svaka cast za znanje i za trud, i puno hvala na ovakvim postovima.
Ja nisam jos sve do kraja proucio, ali cini mi se da sam nabasao na jedan bug u ovom izlaganju. Ispravite me ako gresim:
Code:


    public class Deda
    {
         public virtual void Metod() {}
    }


    public class Unuk: Deda
    {
        public virtual void Metod() {}
    }

    class Class1
    {
        [STAThread]
        static void Main(string[] args)
        {
            Deda d = new Deda();
            Deda u = new Unuk();
            d.Metod();
            u.Metod();
        }
    }


...
Citat:

Iz ovog se vidi da su dva poziva identicna (call dword ptr [eax+38h]), ali opet d.Metod() poziva Deda.Metod, a u.Metod poziva Unuk.Metod() iako su i u i d istog tipa (Deda).

Koliko ja razumem razliku izmedju overrajdinga i zaklanjanja, ovde smo samo zaklonili metod iz klase Deda, tako da ce i d.Metod() i u.Metod() pozivati Deda.Metod() jer su d i u deklarisani kao Deda. Nedostaje nam jedno overide u dekleraciji metoda u klasi Unuk da bi u.Method() pozvao Unuk.Method().
Ako sam u pravu, kako to onda utice na ostale zakljucke iz ovog teksta?
Pozdrav
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: vTable / polimorfizam25.07.2006. u 11:43 - pre 215 meseci
Citat:
Crtani: Ja nisam jos sve do kraja proucio, ali cini mi se da sam nabasao na jedan bug u ovom izlaganju.

Nije bug u tekstu, cisto typo, posto sam kod kucao u text editoru pa ga onda kopirao u VS da izgenerisem MSIL/asm. Naravno ispravio sam ga u VS-u (posto samo virtual bez new nije dovoljan za hiding). Medjutim zaboravio sam da pastujem ispravku nazad u tekst. Nema uticaja na ostatak teksta posto je asemblerski prikaz baziran na override. Izmenio sam post da ne bi bilo zabune.

Kad smo vec kod "new modifier", mali savet. Nemojte nikad to koristiti. To kreira novu lokaciju u vTable koja pocinje da vazi tek od ove klase, efektivno razbijajuci polimorfizam te i buducih klasa u odnosu na pretke. Ja jos nisam video primer u kome bi skrivanje bilo primenljivo u nekoj klasi.

U svakom slucaju hvala na uocenoj gresci...
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

Crtani
Dejan Savic
Beograd

Član broj: 95930
Poruke: 46
*.beobug.com.

Sajt: www.klikeri.net


Profil

icon Re: vTable / polimorfizam25.07.2006. u 13:30 - pre 215 meseci
Citat:
mmix: (posto samo virtual bez new nije dovoljan za hiding)
Tacnije, proslo bi, ali uz upozorenje kompajlera da bi bilo pristojno od nas da mu lepo kazemo sta smo to zamislili... da li planiramo hiding (stavi new) ili overrajding (stavi override). Ako mu ne kazemo, podrazumevace hiding.

I jos jedno pitanje, kad smo vec tu: da je ostalo bez override, kakvu bi VTable za klasu Unuk napravio JIT?
Predpostavljam da bi se tad u njoj naslo mesta za jos jedan Deda.Metod(), a morao bi valjda da ostane i Unuk.Metod()?

Citat:
mmix: Nema uticaja na ostatak teksta posto je asemblerski prikaz baziran na override.
Da. Ovo mi se "javilo" kada sam sve malo detaljnije proucio i razumeo.
Jos jednom: odlican prilog! Fala



 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: vTable / polimorfizam25.07.2006. u 14:54 - pre 215 meseci
Citat:
Crtani: I jos jedno pitanje, kad smo vec tu: da je ostalo bez override, kakvu bi VTable za klasu Unuk napravio JIT?
Predpostavljam da bi se tad u njoj naslo mesta za jos jedan Deda.Metod(), a morao bi valjda da ostane i Unuk.Metod()?


vTable bi izgledao ovako:

Code:

Instanca klase Unuk                           vTable za Unuk 
+------------------------------+              +--------------------------------+
| Pointer na vTable            |  --------->  | <rezervisano ili nevazno>      |
|                              |              | Deda.Staticki()                |
| polje1                       |              | Deda.Metod()                   |
| polje2                       |              | Deda.Metod(int)                |
+------------------------------+              | Deda.Obicni()                  |
                                              | Unuk.Metod()                   |
                                              +--------------------------------+


Problem je jedino sto je potpis metoda isti pa ce kompajler pozvati Unuk.Metod() ako je referenca klase Unuk i njenih naslednika, a Deda.Metod() za sve klase pre Unuk u hijerarhiji. Tj, poziv vise ne zavisi od vTable-a koliko od tipa reference koji nosi instancu, sto je vrlo nesrecno sa stanovista OOP-a

Code:

Deda u = new Unuk();
u.Metod();


ce pozvati Deda.Metod(), ne Unuk.Metod() posto je polimorficki niz za Metod() prekinut u klasi Unuk i prebacen na novu lokciju u vTable
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

[es] :: .NET :: vTable / polimorfizam

[ Pregleda: 2092 | Odgovora: 7 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.