2009-12-15 2 views

ответ

30

Зависит от компилятора.

В VC++ указатель vtable, хранящийся в начале выделения объекта, перед любыми данными элемента. (При условии, что ваш класс имеет хотя бы одну виртуальную функцию-член.)

Также может быть несколько указателей vtable, если ваш класс наследует от других классов с помощью vtables.

Сами файлы статически выделяются где-то в вашем адресном пространстве.

Затем расположение объекта выглядит (для экземпляра C):

A's VTable ptr 
A's member variables. 
B's Vtable ptr 
B's member variables. 
C's member variables. 

для иерархии

class A { 
    virtual Ax() {} 
    int a, b; 
}; 
class B { 
    virtual Bx() {} 
    int c, d; 
}; 
class C : public A, public B { 
    int foo, bar; 
}; 
+16

Я думаю, вы говорите о vptr, то есть указатели на vtables. Сам Vtables обычно хранятся в сегменте статических данных, поскольку они специфичны для класса (по сравнению с объектно-ориентированными). –

+2

Действительно, я поменял свой пост :) –

+1

Макет объекта для экземпляра C, правильно? (В отличие от A, a B и a) – Niklas

1

vptr обычно в начале объекта (Imperfect C++, Backyard Hotrodding C++), но это не гарантируется в стандартном д. Использование vptrs и vtables в стандарте не гарантируется.

Если вам действительно нужно знать, где это, обычно используют что-то вроде COM, XPCOM, UNO и т. Д., Которые реализуются, по существу, с установленным местом, где находится нечто вроде vptr, и задаются способы используй их.

+0

Связи CM и CORBA C++, которые я использовал, оставляют размещение vtable до компилятора C++. – 2009-12-15 12:53:34

+0

Спасибо, я удалил CORBA из списка –

16

Vtable? Что такое vtable? В стандарте C++ не упоминается vtable. Каждый компилятор может реализовать виртуальные функции по своему усмотрению. И это включает в себя размещение виртуальной таблицы в любом месте.

+0

Я считаю, что vtable может быть где угодно, кроме начального адреса объекта. Я понимаю, что адрес первого элемента также является начальным адресом структуры. –

+3

Нет, это не является обязательным требованием. Это относится к типам POD, но типы POD не имеют vtable, поэтому это не проблема. Для типов, отличных от POD, нет гарантии, что адрес структуры совпадает с адресом первого элемента. – jalf

-1

Каждый экземпляр, содержащий виртуальную функцию, имеет указатель виртуальной функции, который указывает на таблицу виртуальных функций (vbtl), мы могли бы найти vtbl через экземпляр. или вы можете использовать objdump для чтения символа файла ELF, возможно, вы найдете ответ. Надеюсь, следующий пример поможет вам.

#include <iostream> 
#include <stdio.h> 
typedef void (*fun_pointer)(void); 

using namespace std; 
class Test 
{ 
public: 
    Test() 
    { 
    cout<<"Test()."<<endl; 
    } 
    virtual void print() 
    { 
    cout<<"Test::Virtual void print()."<<endl; 
    } 
    virtual void print2() 
    { 
    cout<<"Test::virtual void print2()."<<endl; 
    } 
}; 

class TestDrived:public Test 
{ 
public: 
    TestDrived() 
    { 
    cout<<"TestDrived()."<<endl; 
    } 
    virtual void print() 
    { 
    cout<<"TestDrived::virtual void print()."<<endl; 
    } 
    virtual void print2() 
    { 
    cout<<"TestDrived::virtual void print2()."<<endl; 
    } 
    void GetVtblAddress() 
    { 
     cout<<"vtbl address:"<<(int*)this<<endl; 
    } 
    void GetFirstVtblFunctionAddress() 
    { 
    cout<<"First vbtl function address:"<<(int*)*(int*)this+0 << endl; 
    } 
    void GetSecondVtblFunctionAddress() 
    { 
    cout<<"Second vbtl function address:"<<(int*)*(int*)this+1 << endl; 
    } 
    void CallFirstVtblFunction() 
    { 
    fun = (fun_pointer)* ((int*) *(int*)this+0); 
    cout<<"CallFirstVbtlFunction:"<<endl; 
    fun(); 
    } 
    void CallSecondVtblFunction() 
    { 
    fun = (fun_pointer)* ((int*) *(int*)this+1); 
    cout<<"CallSecondVbtlFunction:"<<endl; 
    fun(); 
    } 
private: 
    fun_pointer fun; 
}; 



int main() 
{ 
cout<<"sizeof(int):"<<sizeof(int)<<"sizeof(int*)"<<sizeof(int*)<<endl; 
fun_pointer fun = NULL; 
TestDrived a; 
a.GetVtblAddress(); 
a.GetFirstVtblFunctionAddress(); 
a.GetSecondVtblFunctionAddress(); 
a.CallFirstVtblFunction(); 
a.CallSecondVtblFunction(); 
return 0; 
} 
-2

Vptr и виртуальные таблицы откладываются в сегменте данных ...

виртуальные таблицы, как массив указателя функции.

Vtable и Vptr создают во время компиляции, которая будет получать память во время выполнения, а записи vtable - это адреса виртуальных функций.

Каждый объект класса, содержащего виртуальную функцию, будет иметь дополнительный указатель, который указывает на Виртуальную таблицу, называется виртуальным указателем.

всякий раз, когда мы вызываем виртуальную функцию с использованием объекта, сначала возбуждающий Vptr считывает функцию из Vtable во время выполнения, и, наконец, функция будет вызвана.

Смежные вопросы