jak zmierzyc rozmiar klasy ??

0

Czy mozna jakos zmierzyc rozmiar klasy ?
W strukturach jest to mozliwe dzieki : sizeof(nazwa struktury),czy cos takiego mozna tez zrobic w przypadku klas ?

0

no jasne że można, tyle że nie będzie to rozmiar klasy tylko rozmiar pamięci zaalokowanej przez konstruktor (jumptable+zmienne)

Mniej-więcej tak wygląda pamięć wskazywana przez tajemnicze this

typedef struct myclass{
  void * jumptable // adres ponizszych metod
  void * QueryInterface // metoda 1
  void * AddRef // metoda 2
  void * Release // metoda 3
  void * jakas_metoda_1 // metoda 4 ...
...
  int n_references // ilość referencji do objektu
  int zmienna1
  int zmienna2
}

void * QueryInterface ... jakas_metoda_1 - adresy funkcji (metod) gdzie pierwszy parametr to zawsze this, te adresy wcale nie muszą być kopiowane w to miejsce - mogą być umieszczone w jednym miejscu programu np w sekcji .data:

typedef struct myclass{
  void * jumptable // adres statycznej tabeli skoków np. w segmencie .data
  int n_references
  int zmienna1
  int zmienna2
}
segment .data use32 align=4
tabela_skokow: dd QueryInterface, AddRef, Release, jakas_metoda_1
segment .text

this jest jakąś pamięcią zaalokowaną np. przez GlobalAlloc, IMalloc::Alloc ... musisz sam obadać jaka to pamięć i użyć odpowiedniego API np. GlobalSize(this)
Może być tak, że this jest 4-bajtową pamięcią i wskazuje na jakiś inny blok pamięci który musisz dodatkowo "zmierzyć"
To alokowanie pamięci ma kilka cech: każda instancja jakiegoś obiektu/klasy/interface może mieć swoje prywatne zmienne, metody można podmieniać

W przypadku funkcji CoCreateInstance(..., &ima) gdzie ima jest wskażnikiem do systemowej klasy IMalloc:
ima = adres zmiennej pvtbl
pvtbl = (to jest this)adres pamięci z tabelą skoków, gdzie pierwsze 3 pointery to zazwyczaj interface IUnknown: adresy funkcji QueryInterface, AddRef i Release. Dalsze dwordy z pamięci "this" to adresy funkcji(metod) odpowiednich dla danej klasy, liczba referencji i jakieś zmienne

Jeszcze tak dla przykładu wygląd metody Release:

HRESULT metoda_Release(myclass this/*zawsze jako pierwszy parametr*/)
{
  HRESULT hr;
  this->n_references--;
  hr = this->n_references;
  if (hr=0) GlobalFree( (HGLOBAL)this);
  return hr;
}

Ale to prymitywne wiadomości o COM, jeśli to załapiesz to w assemblerku napiszesz implementacje IContextMenu [green]

0

Ale to prymitywne wiadomości o COM [...]

Nie tylko o COM, ale ogólnie o klasach ;)

0

:| Bez urazy, ale dawno takich andronów nie widziałem. [rotfl] Może i COMa to dotyczy, ale normalnych klas na pewno nie.

Powiedzmy, ze masz takie klasy:

class A {
  int cos_tam;
  void metoda1();
  void metoda2();
};

class B {
 int cos_tam;
 virtual ~B(); 
};

class B {
 int cos_tam;
 virtual ~B(); 
};

class C {
 int cos_tam;
 virtual void metoda1();
 virtual void metoda2();
 virtual void metoda3();
 virtual ~B(); 
};

Zwykle na architekturze 32 bitowej uzyskasz:
sizeof(A) = 4
sizeof(B) = 8
sizeof(C) = 8

Jesli nie uzywasz wirtualnych metod, klasy sa ROWNOWAZNE strukturom, jesli chodzi o rozmieszczenie w pamieci. Nie ma zadnego dodatkowego narzutu pamieciowego.
W przypadku klas z metodami wirtualnymi dodawany jest JEDEN wskaznik na tablice metod wirtualnych i RTTI, niezaleznie od liczby metod. Wskaznik ten jest zawsze na poczatku obiektu. W przypadku wielodziedziczenia, wskaznikow takich moze byc wiecej (jeden na poczatku, inne w srodku obiektu), ale w przypadku pojedynczego dziedziczenia jest zawsze jeden.

0
Krolik napisał(a)

:| Bez urazy, ale dawno takich andronów nie widziałem. [rotfl] Może i COMa to dotyczy, ale normalnych klas na pewno nie.

No przepraszam ale COM'y (a tym bardziej klasy z metodami virtualnymi) to nie są zwykłe klasy??? Owszem, post sapero jest niekonsekwentny (zawiera błędy) i chyba zapomniał dodać, że wszystkie obiekty COM są pochodnymi klas abstrakcyjnych (IUnknown etc.) stąd ta oczywista obecność niejawnego wskaźnika vtable. Więc to nie są aż takie "androny" jak twierdzisz - jest w tym trochę prawdy ;)

0

typedef struct myclass{
  void * jumptable // adres ponizszych metod
  void * QueryInterface // metoda 1
  void * AddRef // metoda 2
  void * Release // metoda 3
  void * jakas_metoda_1 // metoda 4 ...
...
  int n_references // ilość referencji do objektu
  int zmienna1
  int zmienna2
}

To nie dotyczy zwyklych klas, a z postu wynikalo, ze to dotyczy WSZYSTKICH klas, nie tylko COMow. Zwykle klasy nie dostaja np. automatycznie licznika referencji. Odnosnie COMow jest oczysiscie ok.

0
Krolik napisał(a)

To nie dotyczy zwyklych klas, a z postu wynikalo, ze to dotyczy WSZYSTKICH klas, nie tylko COMow.

No tu się mogę zgodzić. Post sapero poruszył tylko jeden aspekt prezentacji obiektów w pamięci. Co oczywiście nie zmienia faktu, że to można odnieść do każdego obiektu posiadającego metody virtualne i temu dałem wyraz w poście ;)

Zwykle klasy nie dostaja np. automatycznie licznika referencji. Odnosnie COMow jest oczysiscie ok.
Tu się nie zgodzę - COM'y też nie dostają licznika referencji, a tym bardziej automatycznego. Za implementacje licznika referencji odpowiedzialny jest programista - dokładnie za implementację metod interface'u IUnknown. Mało tego, za cały reference counting odpowiedzialny jest także programista (lub aplikacja, którą pisze).

0

Zwykle klasy nie dostaja np. automatycznie licznika referencji. Odnosnie COMow jest oczysiscie ok.
Tu się nie zgodzę - COM'y też nie dostają licznika referencji, a tym bardziej automatycznego. Za implementacje licznika referencji odpowiedzialny jest programista - dokładnie za implementację metod interface'u IUnknown. Mało tego, za cały reference counting odpowiedzialny jest także programista (lub aplikacja, którą pisze).

Fakt, mój błąd. [wstyd]

1 użytkowników online, w tym zalogowanych: 0, gości: 1