2012-06-07 37 views
5

Rozumiem, że położenie tabeli wskaźników funkcji w obiekcie jest zależne od kompilatora.
Czy są jakieś zalety/wady umieszczania tego wskaźnika na początku obiektu vs na końcu lub na odwrót?położenie wskaźnika tabeli funkcji wirtualnych w obiekcie

+0

możliwy duplikat [Pobieranie vptr (wskaźnik do wirtualnej tabeli aka VTABLE) z narzędzia Objdump?] (Http://stackoverflow.com/questions/10549311/retrieving-vptrpointer-to-virtual-table-aka-vtablefrom- the-objdump-utility) – iammilind

Odpowiedz

7

Samo istnienie tabeli funkcji wirtualnych jest zależne od kompilatora (ale wszystkie kompilatory robią), a lokalizacja również nie jest wymagana ... We wszystkich kompilatorach, Znam szczegóły, vptr jest przechowywany na początku obiektu. Powodem jest to, że zapewnia jednolitą lokalizację. Rozważmy hierarchię klas:

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

Jeśli vptr przechowywano w końcu obiektu, wtedy byłoby po sizeof(T) bajtów dla obiektu kompletnego typu base. Teraz, gdy masz obiekt kompletnego typu derived, układ obiektu podrzędnego base musi być zgodny z układem kompletnego obiektu base, więc vptr nadal będzie musiał być sizeof(T) bajtów wewnątrz obiektu, który znajdowałby się gdzieś w tym obiekcie. środek obiektu derived (sizeof(T) od początku, sizeof(T1) przed końcem). Tak więc nie byłoby już na obiekcie end. Dodatkowo, biorąc pod uwagę wskaźnik , wywołanie wirtualne wymaga pośredniego przejścia przez tabelę vtable, która w zasadzie polega na dereferencji vptr, dodając przesunięcie i przeskakując do zapisanej tam lokalizacji pamięci. Jeśli vptr był przechowywany na końcu obiektu, dla każdego połączenia wirtualnego byłby dodatkowy dodatek do this przed usunięciem odwołania z vptr.

+0

Teoretycznie możesz mieć vptr zarówno na końcu podobiektu klasy podstawowej, jak i na pełnym obiekcie. Miałoby to sens: używaj vptr 'Derived' dla funkcji wirtualnych, które nie pojawiają się w' Base'. Ale obciążenie na obiekt nie jest takie miłe. – MSalters

+0

Świetne wyjaśnienie !!! –

4

Tak, jest to całkowicie zależne od wdrożenia.
Dla prostej hierarchii dziedziczenia znajduje się na początku obiektu, ale dla złożonej hierarchii nie będzie.
W każdym razie, każdy napisany kod źródłowy nie powinien polegać na tym, gdzie się znajduje, w rzeczywistości każdy napisany kod nie powinien opierać się nawet na istnieniu wirtualnej tabeli lub wirtualnego wskaźnika tabeli.
Standard C++ nie wymaga implementacji wirtualnej wysyłki przez wirtualną tabelę i wskaźnik, implementacja może zaimplementować ją za pomocą innej metody implementacji, jednak wszystkie kompilatory głównego nurtu implementują to za pomocą mechanizmu wskaźnika tabeli, ważne jest, aby pamiętać, że może różnić się dokładną implementacją miejsca, w którym znajduje się wskaźnik itp.