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

Objasnjenje: V-tables?

[es] :: C/C++ programiranje :: Objasnjenje: V-tables?

[ Pregleda: 2500 | Odgovora: 11 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
*.vdial.verat.net.



+9 Profil

icon Objasnjenje: V-tables?27.07.2005. u 21:48 - pre 228 meseci
Da li neko ukratko moze da mi objasni kako funkcionisu VTABLES?
Mislim, lepa je ova knjiga Thinking in C++ :) ali je mnogo... :)
 
Odgovor na temu

Dragi Tata
Malo ispod Kanade

Član broj: 1958
Poruke: 3906
*.dyn.optonline.net.



+6 Profil

icon Re: Objasnjenje: V-tables?28.07.2005. u 02:45 - pre 228 meseci
http://www.elitesecurity.org/tema/31339

 
Odgovor na temu

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
*.vdial.verat.net.



+9 Profil

icon Re: Objasnjenje: V-tables?29.07.2005. u 15:54 - pre 227 meseci
Da, to sam znao... nego, mislio sam da se pojam "V-table" odnosi na nesto drugo, ali koliko sam shavtio to je samo sematski prikaz virtualnih funkcija...
 
Odgovor na temu

erno
Ernad Besirevic
Graz

Član broj: 56944
Poruke: 261
*.liwest.at.



Profil

icon Re: Objasnjenje: V-tables?01.08.2005. u 09:13 - pre 227 meseci
pozdrav,

e pa u V-tabelama su sacuvani svi tzv. V-pointeri koji pokazuju na virtualne funkcije.
a zasto su usopte virtualne funkcije? ok, jedna od primjena je recimo da imas osnovnu klasu Zivotinja i iz te klase su izvedene milion drugih, recimo 5 :-), u svakoj od tih klasa imas jednu overrided funkciju. ako te funkcije nisu definisane kao virtualne, onda ce se uvijek javljati funkcija iz osnovne klase ako imamo:

Zivotinja *nova = new Slon;

u ovom slucaju klasa Slon je izvedena iz osnovne klase Zivotinja te je naslijedila sva svojstva te klase. sta hocu da kazem? iz osnovne klase uvijek mozes dobiti izvedne klase kao sto sam ja to uradio gore. npr. Zivotinja *nova = new Vuk; u ovom slucaju stvorio si objekt tipa Vuk ali ako pozoves tu neku overrided funkciju pokrenuce se ona iz osnovne klase. da bi to izbjegli, tj. da bi se pokretala ona prava funkcija koriste se virtual funkcije koje imaju svoje virtualne tabele (grubo receno) u kojima su virtualni pointeri koji opet pokazuju na tu pravu funkciju. nadam se da ti je pomoglo posto bas i nisam najbolji u objasnjavanju.

pozdrav, erno
 
Odgovor na temu

Goran Arandjelovic
Beograd

Član broj: 29116
Poruke: 387
213.244.203.*



+9 Profil

icon Re: Objasnjenje: V-tables?01.08.2005. u 19:58 - pre 227 meseci
Citat:
e pa u V-tabelama su sacuvani svi tzv. V-pointeri koji pokazuju na virtualne funkcije.


ok, to je ono sto mi je trebalo, a ostalo mi je bilo sasvim jasno (mehanizam v f-ja)
da li se ikako moze 'pristupiti' toj tabeli ili je to nesto fiktivno?
 
Odgovor na temu

leka
Dejan Lekić
senior software engineer, 3Developers
Ltd.
London, UK

Član broj: 234
Poruke: 2534
..31.216.81.gus.vf.siwnet.net.

Sajt: dejan.lekic.org


+2 Profil

icon Re: Objasnjenje: V-tables?12.08.2005. u 01:33 - pre 227 meseci
VTables se koriste samo u slucaju da postoji nekakvo nasledjivanje. Dakle odmah covek moze da shvati da bilo kakvo nasledjivanje klasa odmah znaci (kakav-takav) overhead.
Uzmimo da imamo dve klase Mama i Dete:
Code:

class Mama {
  public:
    virtual void nesto() = 0;
    virtual void ime() { printf("Mama\n"); }
    Mama(int argGodina, int argDece = 1);
    virtual ~Mama();
  private:
    int _godina;
    int _kolikoDece;
};

class Dete {
  public:
    virtual void nesto();
    Dete(int argGodina, bool jedino = false);
    virtual ~Dete();
  private:
    bool _jedino;
};


Ovaj kod se otprilike u C-u "pise" ovako (imajte na umu da nije ceo kod u pitanju):
Code:

typedef int (*VirtualFunctionPointer)();

struct VTable {
  int i;
  int d;
  VirtualFunctionPointer vtableFuncPtr;
};

struct Mama {
  int _godina;
  int _kolikoDece;
  // pokazivac na vtable
  VTable* vtablePtr;
};

struct Dete {
  // Nasledjeno od Mama tipa:
  int _godina;
  int _kolikoDece;
  // Clanovi dodani od strane "Dete" tipa:
  bool _jedino;
  // pokazivac na virtualnu funkciju
  VTable* vtablePtr;
};


Kao sto se vidi svaka struktura koja predstavlja istoimenu klasu u prethodnom kodu poseduje odgovarajuce clanove i OBAVEZNO pokazivac na VTable...

U ovom konkretnom primeru, kako izgleda taj famozni VTable? Pokusacu da sto pribliznije (mada ni ja ne shvatam sve u potpunosti, tako da - ne uzimajte ovo zdravo-za-gotovo) objasnim:

Code:

VTable vtableMama[] = {
  // nesto() je cisti virtuelni metod, te se ne sme direktno zvati
  // zato pozovi pvc_error_handler() funkciju koja ce odmah da prijavi gresku.
  { 0, 0, pvc_error_handler },
  // ime() metod
  { 0, 0, Mama_ime },
  // ~Mama()
  { 0, 0, Mama_destructor}
};

VTable vtableDete[] = {
  // nesto() je virtuelni, ali konkretni, metod
  { 0, 0, Dete_nesto },
  // Poziva bazni ime() metod, jer u ovoj klasi nije definisan.
  { 0, 0, Mama_ime },
  // ~Dete()
  { 0, 0, Dete_destructor}
};


Okej, imamo v-table. I sta sad?
Pa nista bez konstruktora naravno. :)

Code:

Mama* Mama_constructor(Mama* this, int argGodina, int argDece = 1)
{
  if (this == 0) {  // Ako memorija nije alocirana za strukturu Mama:
    this = malloc(sizeof(Mama));
  }
  if (this) { // mozda malloc() ipak nije uspeo...
    // inicijalizuj VTable pokazivac vtablePtr.
    this->vtablePtr = vtableMama;
    this->_godina = argGodina;
    this->_kolikoDece = argDece;
  }
  return this;
}

void Mama_destructor(Mama* this, bool dynamic)
{
  // Ponovo setujemo vtablePtr pointer, jer nije sigurno da on pokazuje na
  // "dobru" vrednost.

/****
  glavno telo destruktora
****/

  this->vtablePtr = vtableMama;
  // Oslobadjamo memoriju SAMO ako je memorija alocirana eksplicitno od strane Mama tipa
  if (dynamic) 
    free(this);
}

Dete* Dete_constructor(Dete* this, int argGodina, int argDece, int argJedino = 0)
{
  if (this == 0) {  // Ako memorija nije alocirana za strukturu Dete:
    this = malloc(sizeof(Dete));
  }
  if (this) { // mozda malloc() ipak nije uspeo...
    // Pozovi prvo konstruktor bazne klase
    Mama_constructor((Mama*)this, argGodina, argDece);
    // inicijalizuj VTable pokazivac vtablePtr.
    this->_jedino = argJedino;
  }
  return this;
}

void Dete_destructor(Dete* this, bool dynamic)
{
  // Ponovo inicijalizujemo vtablePtr pointer, jer nije sigurno da on pokazuje na
  // "dobru" vrednost.
  this->vtablePtr = vtableDete;

/****
  glavno telo destruktora
****/

  // Pozivamo destriktor baznog tipa - Mama
  Mama_destructor((Mama*) this, false);
  // Oslobadjamo memoriju SAMO ako je memorija alocirana eksplicitno od strane Dete tipa
  if (dynamic) 
    free(this);
}


Nema potrebe da pisem kod za ostale metode, ali ima potrebe da objasnim jos jednu stvar u vezi VTables, a to je - kako se koriste podaci iz njih. Tu dolazimo do main() funcije...

Code:

/* ukratko, ipak je 2.11AM ... */

int main()
{
  // Kreiramo objekat tipa Dete, nema smisla kreirati objekat tipa Mama (apstraktna klasa).
  // S obzirom da je prvi argument (this) NULL onda ce se memorija alocirati...
  Mama* mamaPtr = Dete_constructor(NULL, 40, 2, true);
  Dete objekatDete;
  Dete_constructor(&objekatDete, 12, 0, 1);
  // Pozovimo virtuelni metod nesto()
  // Ovaj red je isto sto i: mamaPtr->nesto();
  (mamaPtr->vtablePtr[0].vtableFuncPtr)(mamaPtr);
  // Sledeci red je isto sto i mamaPtr->ime();
  (mamaPtr->vtablePtr[1].vtableFuncPtr)(mamaPtr);
  // Recimo da imamo metod imePrezime(str argIme, str argPrezime)
  // i da imamo negde dve promenljive str1 i str2 tipa str (#define std::string str recimo :)
  // I da je ova funkcija u VTables na mestu sa indeksom 5, onda bi je pozvali sa:
  (mamaPtr->vtablePtr[5].vtableFuncPtr)(mamaPtr, "Marina", "Perazic");
  // C++: delete objekatDete
  Dete_destructor(&objekatDete, false);
  return 0;
}


Dete_destructor linija treba da se pojasni... Naime, memorija je alocirana sa steka za "objekatDete", tako da nema smisla pozivati destructor sa argumentom true, jer ce ta varijabla svejedno da se obrise kada objekatDete izadje iz oblasti vazenja, u ovom slucaju kad se izadje iz funkcije main(). No, ovaj destruktor poziva destruktor bazne klase, te se tako sve lepo ocisti...

Igrom slucaja radim binding jedne C++ biblioteke za jedan maleni interpreter, te je trebalo da "flatten"-ujem C++ klase u C strukture, sa jos par zavrzlama, te otprilike znam kako interno C++ radi sa v-tables. Jos mnogo toga nije jasno, ali stvari lagano dolaze na svoje mesto i sve postaje jako jednostavno i prosto kada se ovo gore shvati.
Dejan Lekic
software engineer, MySQL/PgSQL DBA, sysadmin
 
Odgovor na temu

tosa
上海, 中国

Član broj: 1811
Poruke: 1342
*.ubisoft.com.cn.

ICQ: 14293955
Sajt: https://github.com/milost..


+48 Profil

icon Re: Objasnjenje: V-tables?12.08.2005. u 06:55 - pre 227 meseci
Jos kad bi pointeri na member funkcije bili iste velicine kao "normalni" pointeri,
gde bi nam bio kraj!
 
Odgovor na temu

Dragi Tata
Malo ispod Kanade

Član broj: 1958
Poruke: 3906
*.bowneglobal.com.



+6 Profil

icon Re: Objasnjenje: V-tables?12.08.2005. u 13:12 - pre 227 meseci
Citat:
Leka: Dakle odmah covek moze da shvati da bilo kakvo nasledjivanje klasa odmah znaci (kakav-takav) overhead.


Možda sa GCC-om, ali iole pametni kompajleri jednostavno izbace V-table ako se objekat ne koristi polimorfno.
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
bunuel-cpe-185-bgd.sbb.co.yu.



+1064 Profil

icon Re: Objasnjenje: V-tables?12.08.2005. u 19:21 - pre 227 meseci
Citat:
Dragi Tata: Možda sa GCC-om, ali iole pametni kompajleri jednostavno izbace V-table ako se objekat ne koristi polimorfno.


Ne moze kompajler da izbaci vtable jer on nema uvida u to ko ce sve koristiti objekt
van kompilacione jedinice. To moze jedino linker da stripuje ako je uopste
moguce jer sam layout objekta uveliko zavisi od toga da li postoje virtuelne funkcije.
Ono sto svi kompajleri rade je da call koji se ne dispatch-uje virtuelno, ne izvode kroz vtable
nego direktno.
Potom, vtable se ne koristi samo za virtuelne funkcije vec i za RTTI.

Citat:
tosa: Jos kad bi pointeri na member funkcije bili iste velicine kao "normalni" pointeri, gde bi nam bio kraj!


Tesko da mogu sa obzirom da oni mogu drzati dve razlicite informacije:
ofset u vtable ili pointer na funckiju. Znaci samo adresa/ofset nije dovoljna informacija,
treba i informacija o tome sta pointer predstavlja u datom trenutku.


Citat:
leka: VTables se koriste samo u slucaju da postoji nekakvo nasledjivanje. Dakle odmah covek moze da shvati da bilo kakvo nasledjivanje klasa odmah znaci (kakav-takav) overhead.


vtable nije obavezna implementacija mehanizma virtuelnih funkcija, eto recimo smarteiffel
ne koristi vtable. Drugo, nasledjivanje ne uslovljava vtable uopste, nego postojanje
bar jedne virtuelne funkcije. U tom slucaju se pravi vtable za datu klasu,
bilo nasledjivanja ili ne.

Citat:
leka:
Igrom slucaja radim binding jedne C++ biblioteke za jedan maleni interpreter, te je trebalo da "flatten"-ujem C++ klase u C strukture, sa jos par zavrzlama, te otprilike znam kako interno C++ radi sa v-tables. Jos mnogo toga nije jasno, ali stvari lagano dolaze na svoje mesto i sve postaje jako jednostavno i prosto kada se ovo gore shvati.


Ovo sto radis je sizifov posao, jer sam layout objekta i tabele se menja od kompajlera
do kompajlera. Recimo gcc 2.x.x je drugaciji od gcc 3.x.x, a 4.x.x nisam ni gledao,
tako da moras da vezujes kod za verziju/kompajler koji koristis.

Pozdrav svima, Bane.
 
Odgovor na temu

leka
Dejan Lekić
senior software engineer, 3Developers
Ltd.
London, UK

Član broj: 234
Poruke: 2534
..31.216.81.gus.vf.siwnet.net.

Sajt: dejan.lekic.org


+2 Profil

icon Re: Objasnjenje: V-tables?12.08.2005. u 23:04 - pre 227 meseci
Citat:

Možda sa GCC-om, ali iole pametni kompajleri jednostavno izbace V-table ako se objekat ne koristi polimorfno.

Nemanja, pogresno si me shvatio - ja sam mislio reci da je overhead svaka vrsta polimorfizma. Sto se tice "Možda sa GCC-om" - to necu da komentarisem, nek ide na savest onoga ko je tako nesto izjavio.

[Ovu poruku je menjao leka dana 13.08.2005. u 00:06 GMT+1]
Dejan Lekic
software engineer, MySQL/PgSQL DBA, sysadmin
 
Odgovor na temu

Dragi Tata
Malo ispod Kanade

Član broj: 1958
Poruke: 3906
*.dyn.optonline.net.



+6 Profil

icon Re: Objasnjenje: V-tables?13.08.2005. u 01:50 - pre 227 meseci
Citat:
leka: Nemanja, pogresno si me shvatio - ja sam mislio reci da je overhead svaka vrsta polimorfizma.


Pa kako se uzme. Overhead u odnosu na šta? Bez virtuenih funkcija bi morao da držiš podatke o tipu objekta plus switch-case u svakoj "polimorfnoj" situaciji - izađe mu na isto.

Citat:
leka:
Sto se tice "Možda sa GCC-om" - to necu da komentarisem, nek ide na savest onoga ko je tako nesto izjavio.


Hehehe, ne daj se isprovocirati, Leko, legendo ;)
 
Odgovor na temu

Dragi Tata
Malo ispod Kanade

Član broj: 1958
Poruke: 3906
*.dyn.optonline.net.



+6 Profil

icon Re: Objasnjenje: V-tables?13.08.2005. u 01:57 - pre 227 meseci
Citat:
Branimir Maksimovic: Ne moze kompajler da izbaci vtable jer on nema uvida u to ko ce sve koristiti objekt van kompilacione jedinice.


Jeste, jeste, u stvari sam mislio na pointere na VT, a ne samu VT koja je jedna po klasi. Nego, da nisi ti ovaj:

http://groups-beta.google.com/...m=3&hl=en#29404615dc5dfbab
 
Odgovor na temu

[es] :: C/C++ programiranje :: Objasnjenje: V-tables?

[ Pregleda: 2500 | Odgovora: 11 ] > FB > Twit

Postavi temu Odgovori

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