Unterschied zwischen dem Aufruf der virtuellen Funktion und nicht-virtuelle Funktion?
Dies ist in der Tat eine interview-Frage, ich kann nicht herausfinden, die Antwort. Jeder kennt diese?
Sie können reden, keinen Unterschied, zum Beispiel, die Daten, die push in den stack.
- Was genau ist Ihre Frage?
- Eine virtuelle Funktion erfährt dynamic dispatch. Sollten Sie wählen ein gutes C++ - Buch, um es besser lernen.
- Ich denke, die Frage ist ein bisschen vage. Welche Art von Unterschied bedeutet es? Unterschied ist auf der code-Semantik-Ebene, der compiler-Ebene oder in der Maschine?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Obwohl virtualism/dynamic dispatch ist streng Umsetzung definiert, die meisten(Lesen alle bekannten -) Compiler implementieren Sie mithilfe
vptr
undvtable
.Gesagt, dass der Unterschied zwischen dem Aufruf einer nicht-virtuellen Funktion und virtuelle Funktion ist:
Nicht-virtuelle Funktionen gelöst
statically
beiCompile-time
, Während Virtuelle Funktionen gelöstdynamically
beiRun-time
.Um diese Flexibilität zu erreichen, in der Lage zu entscheiden, welche Funktion aufgerufen wird, zur Laufzeit,
es ist ein wenig Aufwand, im Falle von virtuellen Funktionen.
Einen zusätzlichen
fetch
nennen, die durchgeführt werden muss, und es ist den Aufwand/Preis, den Sie zahlen für die Verwendung von dynamic dispatch.Im Falle einer nicht-virtuellen Funktion die Reihenfolge der Aufrufe ist:
Muss der compiler
fetch
Adresse der Funktion und danncall
es.Während im Fall von virtuellen Funktionen, die Reihenfolge ist:
Muss der compiler
fetch
dievptr
von derthis
, dannfetch
die Adresse der Funktion aus dervptr
und danncall
die Funktion.Dies ist nur eine vereinfachte Erklärung der tatsächlichen Reihenfolge vielleicht weit komplexer als das, aber das ist, was Sie wirklich brauchen, zu wissen, Man muss nicht wirklich wissen müssen, um die Umsetzung nitty gritty ist.
Gut Zu Lesen:
Vererbung & Virtuelle Funktionen
call
. Die Sequenz für ein Funktionszeiger istfetch-call
. Ein vtable-fügt eine weiterefetch
.Wenn Sie eine Basisklasse "Base" und abgeleitete Klasse 'Abgeleitet', und Sie haben eine Funktion "func ()" definiert, die als virtuelle Basisklasse. Diese Funktion ist außer Kraft gesetzt, die von der Abgeleiteten Klasse.
Angenommen, Sie definieren
Dann die 'func' der Abgeleiteten Klasse aufgerufen wird. Während, wenn "func ()" wurde nicht definiert als virtuelle Basis, dann nennt man das aus der 'Base' - Klasse. Das ist der Unterschied, wie der aufrufenden Funktion unterscheidet sich für virtuelle und nicht-virtuelle Funktionen
obj
muss ein Zeiger. 2. Apt zu erwähnen, dass die overidding FunktionDerived::func()
sollten die gleichen Argumente overidding dieBase::func()
Beim Aufruf einer virtuellen Methode, es zu schauen, welche Funktion aufgerufen wird, in eine virtuelle Funktionstabelle.
Den overhead für den Aufruf einer virtuellen Methode ist von Bedeutung.
Auch über diese.
Nicht-virtuelle member-Funktionen gelöst sind statisch. member-Funktion sind Bindung statisch zur compile-Zeit basierend auf dem Typ der pointer (oder Referenz) auf das Objekt.
Im Gegensatz dazu virtuelle member-Funktionen sind Bindung zur Laufzeit dynamisch. Wenn die Klasse mindestens eine virtuelle Memberfunktion dann compiler legt eine versteckte Zeiger in das Objekt, genannt vptr(virtual address-Tabelle) während der Konstruktion des Objekts.
Den compiler erstellt eine v-table für jede Klasse, die mindestens eine virtuelle Funktion. Virtuelle Tabelle enthalten virtuelle Funktion Adresse. Es kann ein array oder eine Liste(abhängig von der compiler des virtuellen Funktionszeiger s
Bei einem Versand an eine virtuelle Funktion, die run-time-system folgt dem Objekt, die v-Zeiger(Holen der Adresse aus dem class-Objekt) der Klasse v-Tabelle-offset Hinzugefügt, um die Basis-Adresse(vptr) und die Funktion aufrufen.
Den Raum-Kosten Aufwand die oben genannten Technik ist nominal: eine zusätzliche Zeiger pro Objekt (aber nur für Objekte, die Notwendigkeit, dynamische Bindung), plus eine zusätzliche Zeiger pro Methode (aber nur für virtuelle Methoden).
Die Zeit-Kosten - Aufwand ist auch ziemlich nominal: im Vergleich zu einer normalen Funktion aufrufen, einen virtuellen Funktionsaufruf erfordert zwei zusätzliche holt (um den Wert der v-Zeiger, eine zweite, um die Adresse der Methode).
Keiner dieser runtime-Aktivität geschieht mit nicht-virtuelle Funktionen, da der compiler löst den nicht-virtuelle Funktionen, die ausschließlich zur compile-Zeit basierend auf dem Typ des Zeigers.
Habe ich genommen einfaches Beispiel zu verstehen, in der besser Art und Weise, wie die Bindung geschah für nicht-virtuelle Funktion & virtuelle Funktion und wie virtual-function-Mechanismus funktioniert.
, Wie die vtable erstellt für Base & abgeleitete Klasse
Assembler-code, der generiert wird, zum besseren Verständnis.
Ich abgerufen haben, die Informationen der vtable von virtuellen.s für die Basis-und Abgeleitete Klasse jeweils:
Wie Sie sehen können, Spaß & fun1 sind nur zwei virtuellen Funktionen in der Basisklasse. Vtable der Basisklasse(_ZTV4Base) Einträge, die von beiden virtuellen Funktionen. Vtable nicht über Eintritt von nicht-virtuellen Funktion. Bitte nicht verwechseln mit dem Namen des Spaßes(ZN4Base3funEv) & fun1(ZN4Base4fun1Ev), Ihren Namen bekam entstellt.
Abgeleitete Klasse vtable haben Baum-Einträge
Wie nicht-virtuelle Funktion & virtuelle Funktion aufgerufen?
für nicht-virtuelle Funktion
Einfach sagen, Holen und Aufruf get(binding geschah zur compile-Zeit)
für nicht-virtuelle Funktion
Holen vptr, fügen Sie die Funktion offset, rufen Sie die Funktion(verbindliche passiert zur Laufzeit)
Montage von 64 ist verwirrend, die meisten c++ - Programmierer, aber wenn alle diskutieren wollen, willkommen