Czy mozna jakos zmierzyc rozmiar klasy ?
W strukturach jest to mozliwe dzieki : sizeof(nazwa struktury),czy cos takiego mozna tez zrobic w przypadku klas ?
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]
Ale to prymitywne wiadomości o COM [...]
Nie tylko o COM, ale ogólnie o klasach ;)
:| 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.
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 ;)
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.
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).
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]