Virtuelle Funktionsaufrufe werden zur Laufzeit mit Bezug auf VTable
der Instanz aufgelöst. Eine eindeutige VTable
existiert für jede virtuelle Klasse (so in oben jeder von A
, B
, C
und haben eine VTable
). Jede Laufzeitinstanz hat einen Zeiger auf eine dieser Tabellen, die durch ihren dynamischen Typ bestimmt wird.
Die VTable
listet jede virtuelle Funktion in der Klasse auf und ordnet sie der tatsächlichen Funktion zu, die zur Laufzeit aufgerufen werden soll. Für die normale Vererbung werden diese in der Reihenfolge der Deklaration aufgelistet, sodass eine Basisklasse das VTable
einer abgeleiteten Klasse zum Deklarieren virtueller Funktionen verwenden kann, die deklariert werden (weil die abgeleitete Klasse, die die Funktionen in Deklarationsreihenfolge aufführt, alle Funktionen der Basisklasse hat) zuerst in genau der gleichen Reihenfolge der Basisklasse eigene VTable
aufgeführt). Für die virtuelle Vererbung (wie oben) ist dies etwas komplizierter, aber im Wesentlichen hat die Basisklasse innerhalb der abgeleiteten Klasse immer noch ihren eigenen Zeiger VTable
, der auf den relevanten Abschnitt innerhalb der abgeleiteten VTable
zeigt.
In der Praxis bedeutet dies, Ihre D
Klasse einen VTable
Eintrag für g
hat, die C
‚s Implementierung zeigt. Selbst wenn über den statischen Typ B
zugegriffen wird, wird immer noch auf VTable
verwiesen, um g
aufzulösen.
Tu dies nicht, das ist der sogenannte Diamant des Todes, siehe https://en.wikipedia.org/wiki/Multiple_inheritance – Bernhard
Ich weiß was es ist, ich will wissen wie es funktioniert. –
Es könnte helfen, wenn Sie erklären, warum Sie denken, dass es so nicht funktionieren würde. Wären Sie auch verwirrt, wenn Sie die erste Zeile von 'main' in' A * b = new D; '? – Hurkyl