30

vtable 存储在内存的哪个位置?

4

6 回答 6

50

取决于编译器。

在 VC++ 中,vtable 指针存储在对象分配的开始,在任何成员数据之前。(前提是你的类至少有一个虚拟成员函数。)

如果您的类从具有 vtables 的其他类乘以继承,也可能有多个 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;
};
于 2009-12-15T04:55:48.830 回答
17

虚拟表?什么虚表?C++ 标准没有提到 vtable。每个编译器都可以按照自己喜欢的方式实现虚函数。这包括将 vtable 放置在它喜欢的任何地方。

于 2009-12-15T12:50:53.597 回答
3

对于 VC++

于 2009-12-15T04:59:13.843 回答
2

vptr 通常位于对象的开头(Imperfect C++Backyard Hotrodding C++),但这在标准中没有得到保证。标准中不保证使用 vptrs 和 vtables。

如果你真的需要知道它在哪里,通常会使用 COM、XPCOM、UNO 之类的东西,这些东西基本上是通过设置一个像 vptr 之类的东西所在的位置并设置使用它们的方式来实现的。

于 2009-12-15T08:04:28.640 回答
-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;
}
于 2013-06-21T16:58:21.843 回答
-2

Vptr 和 Vtable 存储在数据段中...

Vtable 就像一个函数指针数组。

Vtable 和 Vptr 是在编译时创建的,它将在运行时获取内存,而 vtable 条目是虚拟函数地址。

包含虚函数的类的每个对象都会有一个额外的指向虚拟表的指针,称为虚拟指针。

每当我们使用对象调用虚函数时,首先对应的 Vptr 将在运行时从 Vtable 读取函数,最后调用该函数。

于 2016-04-20T05:26:14.827 回答