Reprezentacja klasy

0

Cześć, stworzyłem prosty program celem zobaczenia jak wygląda klasa "od środka".

Oto kod:

class Klasa {
public:
	int x = 10;
	Klasa() { printf("Constructor"); };
	int y = 20;
	void Function() { printf("Function"); }
	int z = 30;
};

int main() {
	Klasa klasa;
	klasa.Function();

	printf("Address - %#x", &klasa);

	getchar();
	return 0;
}

Używając programu do przeglądania pamięci programu wszedłem pod adres klasy i są tam zawarte tylko składowe.
user image

Zmieniłem lekko kod dodając jedną metodę wirtualną:

class Klasa {
public:
	int x = 10;
	Klasa() {};
	int y = 20;
	void Function() { printf("Function"); }
	virtual void VirtualFunction() { printf("VirtualFunction"); }
	int z = 30;
};

int main() {
	Klasa klasa;
	klasa.Function();
	klasa.VirtualFunction();

	printf("Address - %#x", &klasa);

	getchar();
	return 0;
}

Na początku pojawił się nowy wiersz wyglądający na jakiegoś pointera.
user image

Na końcu dodałem jeszcze jedną wirtualną funkcję ale tym razem nie pojawił się żaden nowy pointer.
Czy ktoś może mi wytłumaczyć dlaczego tak się dzieje i dlaczego ten pointer jest wrzucany na sam początek a nie zgodnie z kolejnością jak inne składowe?
Skompilowane przy użyciu Visual Studio 2015 (Toolset v140), optymalizacja kodu całkowicie wyłączona.

class Klasa {
public:
	int x = 10;
	Klasa() {};
	int y = 20;
	void Function() { printf("Function"); }
	virtual void VirtualFunction() { printf("VirtualFunction"); }
	virtual void VirtualFunction2() { printf("VirtualFunction"); }
	int z = 30;
};

int main() {
	Klasa klasa;
	klasa.Function();
	klasa.VirtualFunction();
	klasa.VirtualFunction2();

	printf("Address - %#x", &klasa);

	getchar();
	return 0;
}

user image

6

Dlaczego się tak dzieje? Standard C++ nie definiuje ułożenia zmiennych wewnątrz klas (za wyjątkiem PODów), w różnych poziomach dostępu. Dodatkowo standard C++ nie definiuje sposobu implementacji funkcji wirtualnych (ani wirtualnego dziedziczenia), chociaż chyba wszystkie kompilatory korzystają z vtable.

W uproszczeniu vtable to struktura zawierająca wskaźniki na rzeczywiste implementacje funkcji dla danej instancji, a wskaźnik do takiej struktury (jeden, zamiast kilku) jest trzymany w instancji klasy.

Przy okazji, jeśli używasz VC++ to polecam /d1reportAllClassLayout w linii poleceń jeśli chcesz obejrzeć layouty.

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