2012-06-07 14 views
5

Wie ich verstehe, ist die Position der virtual Funktionszeiger Tabelle in einem Objekt Compiler abhängig.
Gibt es irgendwelche Vor-und Nachteile, diesen Zeiger am Anfang des Objekts vs am Ende oder umgekehrt zu platzieren?Speicherort der virtuellen Funktion Tabellenzeiger in Objekt

+0

möglich Duplikat von [Abrufen von vptr (Zeiger auf virtuelle Tabelle aka VTABLE) aus dem Objdump-Dienstprogramm?] (Http://stackoverflow.com/questions/10549311/retrieving-vptrpointer-to-virtual-table-aka-vtablefrom- the-objdump-utility) – iammilind

Antwort

7

Die bloße Existenz einer virtuellen Funktionstabelle ist Compiler-abhängig (aber alle Compiler tun), und der Ort ist auch nicht zwingend ... In allen Compilern von denen Ich kenne die Details, der VPTR ist am Anfang des Objekts gespeichert. Der Grund ist, dass es einen einheitlichen Standort bietet. Betrachten wir eine Klassenhierarchie:

struct base { 
    T data; 
    virtual void f(); 
}; 
struct derived : base { 
    T1 data; 
    virtual void g(); 
}; 

Wenn die vptr am Ende des Objekts gespeichert wurde, dann wäre es für ein Objekt von kompletten Typ base nach sizeof(T) Bytes sein. Wenn Sie nun ein Objekt vom vollständigen Typ derived haben, muss das Layout des Unterobjekts base mit dem Layout eines vollständigen base Objekts kompatibel sein, so dass vptr immer noch sizeof(T) Bytes innerhalb des Objekts sein müssten, was irgendwo in der Mitte des derived Objekts (sizeof(T) von Anfang an, sizeof(T1) vor dem Ende). So wäre es nicht mehr am Ende des Objekts. Ein virtueller Aufruf erfordert zusätzlich eine Indirektion durch die vtable, die im Grunde den vptr dereferenziert, einen Offset hinzufügt und zu dem Speicherort springt, der dort gespeichert wird. Wenn die vptr am Ende des Objekts gespeichert wurde, gibt es für jeden virtuellen Aufruf eine zusätzliche Ergänzung zu this vor der Dereferenzierung der vptr.

+0

Theoretisch könnten Sie vptrs sowohl am Ende des Unterobjekts der Basisklasse als auch des vollständigen Objekts haben. Es würde einen Sinn ergeben: den "Abgeleiteten" vptr für virtuelle Funktionen haben, die nicht in "Base" erscheinen. Aber der Overhead pro Objekt ist nicht so schön. – MSalters

+0

Große Erklärung !!! –

4

Ja, es ist vollständig implementierungsabhängig.
Für eine einfache Vererbungshierarchie befindet es sich am Anfang des Objekts, aber für eine komplexe Hierarchie wird es nicht sein.
Irgendein Quellcode, den Sie schreiben, sollte sich nicht darauf verlassen, wo er sich befindet, tatsächlich sollte sich jeder Code, den Sie schreiben, nicht auf die Existenz einer virtuellen Tabelle oder eines virtuellen Tabellenzeigers verlassen.
Der C++ Standard schreibt nicht vor, dass virtueller Versand durch virtuelle Tabelle und Zeiger implementiert wird, eine Implementierung ist frei, sie unter Verwendung einer anderen Implementierungsmethode zu implementieren. Jedoch implementieren alle gängigen Compiler dies über Tabellenzeigermechanismus kann sich in der genauen Implementierung unterscheiden, wo der Zeiger sich befindet usw.