Hier unterscheidet sich die Signatur der Funktion fn, die in der Klasse base
definiert ist, von der Signatur der Funktion fn()
, die in der Klasse der
definiert ist, obwohl der Funktionsname gleich ist.
Die in der
class definierte Funktion blendet daher base
class function fn()
aus. Die Klasse der
version von fn kann nicht von p->fn(i)
call aufgerufen werden; Es ist in Ordnung.
Mein Punkt ist dann warum sizeof
class base
oder der
ist 4
wenn es keinen VTABLE Pointer gibt? Was ist Voraussetzung für VTABLE Pointer hier?
Beachten Sie, dass dies in hohem Maße von der Implementierung abhängt & amp; könnte für jeden Compiler variieren.
Voraussetzung für das Vorhandensein von vtable
ist, dass die Base-Klasse für die Vererbung und Erweiterung gedacht ist und eine davon abgeleitete Klasse die Methode überschreiben könnte.
Die beiden Klassen Base und Derived können sich in verschiedenen Übersetzungseinheiten befinden und der Compiler wird beim Kompilieren der Base-Klasse nicht wirklich wissen, ob die Methode überschrieben wird oder nicht. Also, wenn es das Schlüsselwort virtual
findet, erzeugt es vtable
.
Die vtable wird normalerweise nicht nur für virtuelle Funktionen verwendet, sondern dient auch dazu, den Klassentyp zu identifizieren, wenn Sie dynamic_cast
ausführen oder wenn das Programm auf die type_info
für die Klasse zugreift.
Wenn der Compiler feststellt, dass keine virtuellen Funktionen überschrieben werden und keines der anderen Features verwendet wird, kann den vtable-Zeiger als Optimierung entfernen.
Offensichtlich hat der Compiler-Schreiber es nicht die Mühe wert gefunden, dies zu tun. Wahrscheinlich, weil es nicht sehr oft verwendet wird, und weil Sie es selbst tun können, indem Sie das virtual
aus der Basisklasse entfernen.
Der Compiler kann die vtable
-Membervariable nicht aus der 'base'-Klasse heraus optimieren, da es eine andere Quelldatei innerhalb desselben oder eines anderen Projekts geben könnte, die Folgendes enthalten würde:
Der Destruktor und fn
könnten woanders implementiert werden:
Und irgendwo an einem anderen Ort könnte Code wie folgt sein:
%Vor% Es würde also zwei Probleme geben: virtuelle Funktion ived::fn
nicht aufgerufen, virtueller Destruktor nicht aufgerufen, also BIG_DATA_SIZE
nicht gelöscht. Ansonsten wäre sizeof(base)
hier anders. Aus diesem Grund erzeugen Compiler immer vtable
für jede Klasse mit einer virtuellen Member-Funktion oder einer virtuellen Basisklasse.
Beim Aufrufen von Destruktoren in abgeleiteten Klassen muss dies als Muss betrachtet werden: Wenn Sie eine Klasse mit einer virtuellen Funktion haben, muss diese Klasse auch einen virtuellen Destruktor deklarieren.
Die Vererbung ist eine is-a
-Beziehung. der
ist -a base
. base
hat die Größe 4
, der
hat mindestens die Größe 4
. vftableptr
ist ein Mitglied von base
, es ist ein Mitglied von der
.
base
hat eine virtuelle Methode, daher wird es einen Zeiger auf die virtuelle Tabelle haben, unabhängig davon, ob Sie es verwenden oder nicht.
Tags und Links c++ override virtual-functions vptr