PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Vtables in C++


Grundkurs
2019-06-19, 07:28:57
Moin! Ich habe mich gestern mit der Implementierung von virtuellen Funktionen in C++ beschäftigt und verstehe eine Sache nicht richtig. In jeder Erklärung zum Thema werden folgende Aussagen getroffen:
1. Enthält eine Basisklasse eine virtuelle Funktion wird für diese Basisklasse sowie jeweils jede abgeleitete Klasse ein eigenes vtable erstellt, das die Adressen aller virtuellen Funktionen speichert, wobei immer die Adresse der "tiefsten" virtuellen Funktion gespeichert wird. Implementiert eine abgeleitete Klasse daher eine eigene virtuelle Funktion, wird die Adresse dieser Funktion in ihrem vtable gespeichert, ansonsten zumindest die virtuelle Funktion aus der Basisklasse oder einer anderen von dieser abgeleiteten Klasse.

2. Jedes konkrete Objekt erhält einen vtable-pointer, der auf das richtige vtable zeigt, das zu derselben Klasse gehört wie das erzeugte Objekt: vtable-pointer von Cat-Objekt zeigt auf vtable von Cat-Klasse. Soweit so klar.

Was ich jetzt nicht begreife: wie kann der vtable denn nun die zum Objekt passende virtuelle Methode des Objekts aufrufen? Objekt und Klasse sind ja zwei verschiedene Dinge. Es gibt doch nur
ein "statisches" vtable je Klasse. Woher soll dieses wissen welche Objekt-Methode aufgerufen werden soll? Wird dafür etwa für jedes Objekt eine eigene vtable erstellt die immer denselben Aufbau hat (sprich ein vtable für jede Klasse), aber faktisch wird für jedes Objekt ein separates vtable erzeugt dass alle relevanten Speicherorte der virtuellen Methoden des jeweiligen Objekts speichert? Ich verstehe den Sprung von "statisches" vtable zu konkretes Objekt nicht.

Ganon
2019-06-19, 07:52:33
So wie du es unter 2. beschrieben hast. Wenn du eine Funktion von einem Objekt aufrufst, dann "geht" es zur vtable die dem Objekt über den vtable-Pointer zugewiesen ist.

Du kommst ja vom Objekt und "springst" dann zur Klasse, nicht anders herum.

Grundkurs
2019-06-19, 08:01:03
Genau. Vtable-Pointer des konkreten Objekts zeigt auf vtable, von dort aus wird nun die "richtige" virtuelle Funktion aufgerufen. Ich habe hier ein Verständnisproblem: ich dachte jedes Objekt besitzt seinen eigenen Satz an Member-Variablen und Funktionen. Wie komme ich nun vom vtable zurück zum Funktionsaufruf der spezifischen Funktion eines spezifischen Objekts? Die vtable kennt das konkrete Objekt ja nicht.

Demirug
2019-06-19, 08:02:09
Du hast es doch schon geschrieben. Jede Objektinstanz enthält einen durch den Compiler erzeugten versteckten Parameter welcher auf die statische ein vorhandene vtable der entsprechenden Klasse verweist.

edit:

Du rufst ja nicht eine spezifische Funktion eines Objekts auf sondern die spezifische Funktion der Klasse des Objekts. Das Objekt kennt seine Klasse und kann daher beim Aufruf die richtige Funktion für diese Klasse aus der vtable der Klasse holen. Praktisch passiert beim Aufruf einer virtuellen Methode folgendes.

1. Es wird die Adresse der vtable aus dem Objekt geholt
2. Es wird die Adresse der benötigten Funktion aus der vtable geholt
3. Es wird die an dieser Adresse ausgeführte Funktion ausgeführt.

Damit die Funktion nun weiß für welches Objekt sie ausgeführt wird gibt der Compiler einen Zeiger auf das Objekt selbst als versteckten Parameter mit. Das gilt aber für alle Funktionsaufrufe von nicht statischen Methoden.

Bei Mehrfachvererbungen wird das ganze etwas komplizierter daher spare ich mir das erst mal.

Grundkurs
2019-06-19, 08:10:50
Damit die Funktion nun weiß für welches Objekt sie ausgeführt wird gibt der Compiler einen Zeiger auf das Objekt selbst als versteckten Parameter mit. Das gilt aber für alle Funktionsaufrufe von nicht statischen Methoden.

Das war das Puzzle-Stück das mir zum Verständnis gefehlt hat, danke für die Erklärung!