vtable 存储在内存的哪个位置?
6 回答
取决于编译器。
在 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;
};
虚拟表?什么虚表?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 读取函数,最后调用该函数。