2016-04-10 19 views
2

Ich habe viele Beiträge gelesen und jeder sagt, dass virtuelle Tabelle pro Klasse ist, nicht pro Objekt und Objekt hat nur _vtpr Zeiger auf freigegebene vtable. Aber bitte betrachten Sie dieses Beispiel:Virtuelle Tabelle in Polymorphismus

class Base 
{ 
public: 
    virtual void func1(void) {} 
    virtual void func2(void) {} 
private: 
    int dummy; 
}; 

class Der1 : public Base 
{ 
public: 
    virtual void func1(void) {} 
private: 
    int dummy; 
}; 

class Der2 : public Base 
{ 
public: 
    virtual void func2(void) {} 
private: 
    int dummy; 
}; 

int main(void) 
{ 
    Base * obj1 = new Der1; 
    Base * obj2 = new Der2; 
} 

Hat obj1 und obj2 betrifft, dass eine einzigartige Basisklasse VTable? Ich glaube die Antwort ist nein, aber kannst du es bitte erklären? Und wenn beide Objekte sich auf dieselbe vtable beziehen, wie wird bestimmt, welche Methoden aufgerufen werden sollen? Zum Beispiel unterscheidet sich obj1-> func1 reference von obj2-> func1.

UPDATE:
welche Operationen ausgeführt werden, wenn Base * obj1 = new Der1; tun? Kann jemand einen Pseudocode für diese Aktionen schreiben?

+2

vtable ist nicht im C++ - Standard definiert. Es bedeutet, dass Compiler-Implementierer frei tun können, was sie wollen. Es gibt sogar keine Garantie, dass überhaupt eine VTable vorhanden sein wird. Dies ist einer der Hauptgründe, warum wir keinen C++ ABI haben. Sag das an "alle", die "sagen". – Drop

+0

Vermutlich haben 'Der1' und' Der2' jeweils eine eigene vtable, nicht? –

+1

Bitte überprüfen Sie diese [Antwort] (http://stackoverflow.com/a/562240/2352671) von [Johannes Schaub - litb] (http://stackoverflow.com/users/34509/johannes-schau-litb) – 101010

Antwort

1

Ich hoffe, die folgende Abbildung wird Ihnen helfen. Abgeleitete Klassen kopieren nur die virtuelle Tabelle der Basisklasse, aber sie können den entsprechenden Eintrag ändern. Der rote Teil zeigt, dass die gegebene Klasse den Eintrag in der v-Tabelle geändert hat. Wenn also die Instanz der abgeleiteten Klasse erstellt wird, wird die (für diese Klasse spezifische) modifizierte Tabelle berücksichtigt.

Es ist Sache des Compilers, wie die Duplizität der Basisklasse gehandhabt wird (wenn die Basisklasse eine große Anzahl von Funktionen hat - würde eine Kopie der gesamten virtuellen Funktionstabelle erhalten und würde die Einträge modifizieren?). IMO, Compiler wird einfach ganze Tabelle für jede abgeleitete Klasse kopieren, um Dinge einfach zu halten. Das Suchen der geeigneten Methode zum Anrufen wird dann einfach. enter image description here

+0

Wo und wann werden neue Vtables gefunden? Korrigiere mich, wenn ich falsch liege: Bei der Kompilierung werden Der1 und Der2 Vtables in den RW Datenbereich erstellt; Bei der Zuweisung von Base * obj1 = new Der1; und Aufruf von obj1-> func1(), Der1 vtable wird dereferenziert, um den Eintrag dieser bestimmten Methode zu finden. Und da Base * obj1 und obj2 nur Zeiger sind, haben sie nicht und kopiert nach vtable. –

+0

Also können Sie mein Verständnis dafür oder ich bin falsch? –

+0

Ich weiß nicht über Datenabschnitte, und wie Compiler/Linker genau die V-Tabellen setzt. Konzeptionell können Sie V-Tabellen als global verknüpfte Listen betrachten. Eine gegebene Klasse enthält einen Kopf der v-Tabelle (und daher wird die Größe der Klasse um 'sizeof (pointer)' hinzugefügt). Eine abgeleitete Klasse würde eine andere verknüpfte Liste der v-Tabelle erstellen, und die Klasse (nicht die Instanz) würde auf diese verknüpfte Liste zeigen. Wenn die abgeleitete Klasse eine virtuelle Funktion nicht neu definiert, würde sie auf eine existierende v-table verknüpfte Liste zeigen. Eine virtuelle Klassenhierarchie kann auf mehrere solcher verketteten Listenköpfe zeigen, und daher wird die Größe erhöht. Bitte lesen Sie das Buch/onlin – Ajay