Virtuelle Tabellen und virtuellen Zeiger für mehrere virtuelle Vererbung und Typumwandlung
Ich bin etwas verwirrt über vptr und Darstellung der Objekte in den Speicher, und hoffe Ihr könnt mir helfen zu verstehen die Sache besser.
- Betrachten
B
erbt vonA
und beide definieren virtuelle Funktionenf()
. Von dem, was ich gelernt, die Repräsentation eines Objekts der Klasse B im Speicher sieht wie folgt aus:[ vptr | A | B ]
und dievtbl
dassvptr
Punkte enthältB::f()
. Ich habe auch verstanden, dass durch die Umwandlung des Objekts ausB
zuA
tut nichts, außer das ignorieren derB
Teil an das Ende des Objekts. Ist es wahr? Nicht dieses Verhalten falsch ist? Wir wollen, dass das Objekt des TypsA
ausführenA::f()
Methode und nichtB::f()
. - Gibt es eine Reihe von
vtables
im system als die Anzahl der Klassen? - Wie wird ein
vtable
von der Klasse erbt, die aus zwei oder mehr Klassen Aussehen? Wie wird das Objekt von C dargestellt werden, in den Speicher? - Gleiche wie Frage 3, aber mit der virtuellen Vererbung.
InformationsquelleAutor Artium | 2010-07-24
Du musst angemeldet sein, um einen Kommentar abzugeben.
Folgendes gilt für den GCC, aber kann auch wahr sein, damit der compiler Sie verwenden. All dies ist von der Implementierung abhängig, und unterliegen daher nicht der C++ - standard. Jedoch, GCC schreiben Sie Ihre eigene binäre standard-Dokument, Itanium ABI.
Ich versuchte zu erklären, grundlegende Konzepte wie virtuelle Tabellen angelegt werden, in mehr einfachen Worten, wie ein Teil meiner Artikel über virtuelle Funktion performance in C++, die Sie nützlich finden können. Hier erhalten Sie Antworten auf Ihre Fragen:
Einen richtigeren Weg zu zeigen interne Darstellung des Objekts:
B
enthält seiner Basis-KlasseA
, es fügt nur ein paar seiner eigenen Mitglieder nach deren Ende.Casting von
B*
zuA*
ja, macht nichts, es gibt die gleichen Zeiger und dievptr
bleibt die gleiche. Aber, in einer nussschale, virtuelle Funktionen sind nicht immer genannt, über die vtable. Manchmal nennt man Sie, genau wie die anderen Funktionen.Hier finden Sie weitere ausführliche Erklärung. Sollten Sie unterscheiden zwei Möglichkeiten der Aufruf member-Funktion:
Die Sache ist die, dass es bekannt zur compile-Zeit, wie die Funktion aufgerufen werden: über vtable-oder einfach nur ein üblichen call. Und die Sache ist, dass der Art einer casting-Ausdruck zur Kompilierzeit bekannt ist, und damit der compiler wählt die richtige Funktion zur compile-Zeit.
Es gar nicht von innen sehen vtable in diesem Fall!
In der Regel, Nein. Eine Klasse kann mehrere vtables wenn es erbt von mehreren Basen, die jeweils eigene vtable. Solche virtuellen Tabellen bildet eine "virtuelle Tabelle-Gruppe" (siehe pt. 3).
Klasse muss auch eine Reihe von Bau-vtables, richtig distpatch virtuelle Funktionen beim Aufbau von Grundlagen für ein Komplexes Objekt. Lesen Sie weiter in die standard-I verbunden.
Hier ist ein Beispiel. Übernehmen
C
erbt vonA
undB
jede Klasse definierenvirtual void func()
sowiea
,b
oderc
virtuelle Funktion relevant sein name.Den
C
wird eine vtable Gruppe von zwei vtables. Es wird in teilen eine vtable mitA
(die vtable, wo die eigenen Funktionen der aktuellen Klasse gehen wird als "primäre"), und eine vtable fürB
werden angefügt:Die Darstellung der Objekt im Speicher Aussehen wird fast der gleichen Weise Ihr vtable sieht. Fügen Sie einfach ein
vptr
vor jeder vtable in einer Gruppe, und Sie haben eine grobe Schätzung, wie die Daten angelegt werden, innerhalb des Objekts. Sie können darüber Lesen Sie in der relevante Abschnitt der GCC Binär-standard.Virtuellen Basen (einige von Ihnen) angelegt werden, am Ende der vtable-Gruppe. Dies geschieht, weil jede Klasse sollte nur eine virtuelle Basis, und wenn Sie waren vermischt mit den "üblichen" vtables, dann compiler konnte nicht re-Teile gebaut vtables zu machen, diejenigen, die von abgeleiteten Klassen. Dies würde dazu führen, computing unnötig, die Abstände und die Leistung verringern würde.
Durch solch eine Platzierung, virtual Grundlagen auch eine Einführung in Ihre vtables zusätzliche Elemente:
vcall
offset (Adresse für den final overrider beim springen aus dem Zeiger auf eine virtuelle Basisklasse innerhalb eines vollständigen Objekts an den Anfang der Klasse, überschreibt die virtuelle Funktion) für jede virtuelle Funktion definiert. Auch die einzelnen virtuellen Basis fügtvbase
offsets, die eingefügt werden, vtable von der abgeleiteten Klasse enthalten; Sie lassen, um herauszufinden, wo die Daten der virtuellen Basis beginnen (es kann nicht kompiliert werden, da die tatsächliche Adresse hängt von der Hierarchie: virtuelle Basen werden am Ende des Objekts, und die Verschiebung von Anfang variiert je nachdem, wie viele nicht-virtuelle Klassen die aktuelle Klasse erbt.).Wuff, ich hoffe, ich habe nicht vorstellen, viel unnötige Komplexität. In jedem Fall finden Sie der ursprünglichen standard, oder zu einem beliebigen Dokument eigene compiler.
InformationsquelleAutor P Shved
Ich würde empfehlen, das Lesen Mehrfachvererbung Als Nützlich , es ist ein langer Artikel, aber es macht die Dinge klarer, über das Thema, wie Sie erklärt, in großem Detail, wie die Vererbung funktioniert in C++ (die zahlen links funktionieren nicht, aber Sie sind am unteren Rand der Seite).
InformationsquelleAutor Klaim
Wenn Objekt B erbt von A und dann die Speicher-Darstellung für B wird folgende sein:
Wenn Sie B* b = new B(); (A)b->f (), dann:
Jedes Objekt hat seine eigene vtable (nehmen Sie das nicht für selbstverständlich, wie ich haben, um es zu erforschen
Werfen Sie einen Blick auf diese ein Beispiel für die vtable-layour beim Umgang mit mehrfacher Vererbung
Sehen diese für eine Diskussion über die diamond Vererbung und der vtable-Darstellung
(A)b
ist nicht ein Zeiger cast, Sie bauen ein anderes ObjektInformationsquelleAutor Ando