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
Odpowiedz
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ę :-)
to jest tak naprawdę chciałem. –
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
@ user1764961- yaa naprawdę niewiarygodny człowiek !! –
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.
W języku C++ nie jest konieczne, aby kompilator używał tabeli V do implementowania funkcji wirtualnych ??? –
@ user2484070 tak, to nie jest konieczne. Implementacja funkcji wirtualnych zależy od kompilatora. – ForEveR
@ 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
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ć.
mam to. dzięki :) –
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ć.
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. –
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. –