Где в памяти хранится vtable?

Где в памяти хранится vtable?

6 ответов

Решение

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

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

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

Сами 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;
};

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

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

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

Каждый экземпляр, который включает в себя виртуальную функцию, имеет указатель виртуальной функции, который указывает на таблицу виртуальных функций (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;
}

Vptr и Vtable хранятся в сегменте данных...

Vtable похож на массив указателей на функции.

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

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

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

Другие вопросы по тегам