Warum wird ein vptr benötigt, wenn die abgeleitete Klasse die virtuelle Funktion nicht überschreibt?

8
%Vor%

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?

    
user966379 02.02.2012, 09:11
quelle

4 Antworten

6

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 .

    
Alok Save 02.02.2012, 09:13
quelle
1

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.

    
Bo Persson 02.02.2012 09:27
quelle
1

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:

%Vor%

Der Destruktor und fn könnten woanders implementiert werden:

%Vor%

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.

    
Alexey Omelchenko 23.04.2016 07:42
quelle
0

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.

    
Luchian Grigore 02.02.2012 09:18
quelle