2013-06-14 34 views
7

Ponieważ cała wirtualna funkcja w C++ jest przechowywana w tabeli V. Zastępowanie ma miejsce w przypadku funkcji wirtualnej. Chciałbym zapytać, czy istnieje sposób, w jaki możemy wywołać funkcję wirtualną bezpośrednio z tabeli i określić, jakie funkcje zawiera tabela V.Wywołanie funkcji wirtualnej z tabeli V

+0

Dlaczego ktoś chciałby to zrobić? Przynajmniej możesz (używając jakiegoś bezpośredniego adresowania pamięci), o ile wiesz o inernaliach kompilatora ABI. –

+0

możemy zrobić coś ze wskaźnikiem V, który jest obecny w klasie (jeśli klasa zawiera funkcje wirtualne), która wskazuje na v-table.using G ++ kompilator, próbowałem za pomocą wskaźnika V, ale nie działa. –

Odpowiedz

16

Cóż, w rzeczywistości możesz. Nie dbam o przenośność, ale w VS możesz to zrobić. Zakładając, że budujemy kod 32-bitowy z VS, pierwsze 4 bajty adresu obiektu to adres vtable. Patrząc na pliki nagłówkowe znamy kolejność metod w vtable.

przykład:

class Base 
{ 
public: 

    virtual void printMessage() 
    { 
     std::cout << "Base::printMessage()" << std::endl; 
    } 
}; 

class Derived : public Base 
{ 
public: 

    void printMessage() 
    { 
     std::cout << "Derived::printMessage()" << std::endl; 
    } 
}; 

int main(int argc, char* argv[]) 
{ 
    Derived d; 

    unsigned int vtblAddress = *(unsigned int*)&d; 

    typedef void(*pFun)(void*); 

    pFun printFun = (pFun)(*(unsigned int*)(vtblAddress)); 

    printFun(&d); 

    return 0; 
} 

P.S. Nie zamierzam pytać, dlaczego to robisz, ale tutaj masz jedną opcję :-)

+1

to jest tak naprawdę chciałem. –

+8

Niewiarygodne, Peter Wood, Eelke, toro2k, Stony i quetzalcoatl nie są w stanie powiedzieć, o co tu chodzi. Jak to się stało, że każdy uczestnik tego wątku zrozumiał, o co pyta? 5 "Inteligentnych" facetów z całkiem niską reputacją w porównaniu do Mike'a Seymoura i ForEveR'a, pieprzą wszystkich. Mam na myśli, że nie rozumiesz pytania, to w porządku, ale niech inni dyskutują o tym na litość boską ... – user1764961

+1

@ user1764961- yaa naprawdę niewiarygodny człowiek !! –

2

Standardowo nie ma gwarancji, że funkcje wirtualne są realizowane za pomocą v-table. Tak więc, tylko jeśli jesteś pewien, że ten kompilator używa v-table - możesz znaleźć potrzebne przesunięcie.

+1

W języku C++ nie jest konieczne, aby kompilator używał tabeli V do implementowania funkcji wirtualnych ??? –

+0

@ user2484070 tak, to nie jest konieczne. Implementacja funkcji wirtualnych zależy od kompilatora. – ForEveR

+0

@ user2484070, wartości będą przechowywane gdzieś i jakoś, to na pewno. Czy to będzie dobrze znany V-stół, czy coś innego ... naprawdę nie ma znaczenia. – user1764961

2

Przenośnie, nie. Język nie określa, w jaki sposób wdrażana jest wysyłka wirtualna, tylko jak się zachowuje. Niekoniecznie jest implementowane przy użyciu v-table i nie ma możliwości uzyskania dostępu do funkcji wirtualnej, z wyjątkiem wywoływania tego.

Jeśli potrzebujesz obsługi tylko jednego określonego ABI, możesz użyć szczegółów implementacji wraz z pewnymi rzucanymi rzutkami, aby odwzorować obiekt na wskaźnik funkcji w taki sam sposób, jak robi to mechanizm wirtualnej wysyłki. Ale przejdziesz poza zdefiniowany język na nieobsługiwane, nieprzenośne terytorium, więc zdecydowanie polecam ponowne przemyślenie tego, co próbujesz zrobić.

+1

mam to. dzięki :) –

0

Powiedziałbym nie ogólnie, ponieważ dokładna implementacja vtable jest specyficzna dla platformy/kompilatora. Jeśli wiesz, w jaki sposób platforma/kompilator implementuje tabelę i adresowanie, możliwe jest obliczenie jej poprzez określenie adresu tabeli vtable dla określonej klasy, a następnie dodanie przesunięcia metody wirtualnej.

Zestaw vtable zawiera wszystkie metody wirtualne dla tej klasy. Możesz zdemontować aplikację, aby je zobaczyć.