揭开C++类中虚表的“神秘面纱”

时间:2021-06-23 19:03:01

  C++类中的虚表结构是C++对象模型中一个重要的知识点,这里咱们就来深入分析下虚表的在内存中的结构。

  C++一个类中有虚函数的话就会有一个虚表指针,其指向对应的虚表,一般一个类只会有一个虚表,每个虚表有多个”插槽”,每个插槽存放一个虚函数的地址。插槽中的内容可以被覆盖,子类如果重写了父类中的虚函数,则插槽中对应位置的数据被覆盖。虚表存放的是虚函数地址,不管该虚函数是public还是private的。光文字说明不太形象,下面上一张虚表结构的示例图:

aaarticlea/png;base64,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" alt="" />

  从图中看出,虚表指针确实是指向虚表结构的,这个虚表结构中有许多插槽,每个插槽都会指向一个虚函数。那么如何用程序来测试呢,请接着看:

 #include <iostream>
#include <cstdio> using namespace std; class Base {
public:
virtual void test() {
cout << "Base.text()" << endl;
} public:
int a;
}; class Derived : public Base {
public:
virtual void test() {
cout << "Derived.test()" << endl;
} public:
int b;
}; typedef void (*PFunc)(); int main() {
Derived derived;
PFunc ptest; // 函数指针 // 输出derived及其成员a/b的地址
printf("derived: %p\n", &derived);
printf("derived.a: %p\n", &(derived.a));
printf("derived.b: %p\n", &(derived.b)); // 提取出test虚函数地址
int *p = (int *)*(int *)(&derived);
ptest = (PFunc)*p;
ptest(); return ;
}

输出结果:

揭开C++类中虚表的“神秘面纱”

  注意,程序是在Centos 7 64位系统下进行测试的。程序中直接提取出test虚函数地址,然后进行调用,发现调用的确实是Derived.test函数,这也说明了虚表结构的内存布局。

关于虚表几个有意思的问题

虚表指针什么时候赋值的?

 #include <iostream>

 using namespace std;

 class Base
{
public:
Base() {
cout << "Base()" << endl;
show();
int *p = &b;
cout << "Base::b: " << p << endl;
p = (int *)((char *)p - );
cout << "Base::vptr: " << *p << endl;
// Base中虚函数地址
cout << "*Base::vptr: " << *(int *)*p << endl;
cout << endl;
} virtual void show() {
cout << "Base::show()" << endl;
}
public:
int b;
};
class Derived : public Base
{
public:
Derived()
{
cout << "Derived()" << endl;
show();
int *p = &b;
cout << "Derived::b: " << p << endl;
p = (int *)((char *)p - );
cout << "Derived::vptr: " << *p << endl;
// Derived中虚函数地址
cout << "*Derived::vptr: " << *(int *)*p << endl;
cout << endl;
}
virtual void show() {
cout << "Derived::show()" << endl;
}
private:
int d;
}; int main(int argc, char **argv)
{
Base base;
Derived derived; return ;
}

输出结果为:

揭开C++类中虚表的“神秘面纱”

从输出结果中可以得出,子类在构造过程中虚表指针会被赋值2次。初始化如下:

  基类静态成员 – 子类静态成员 – (设置v_ptr/基类成员变量 ) –基类构造函数 – (设置v_ptr/子类成员变量) – 子类构造函数

在类的析构函数中是否对虚表指针进行赋值操作呢?

  在子类的析构函数中,会把虚表指针设置为指向父类中的虚函数地址,这样在父类的析构函数中调用虚函数实际上调用的是父类的虚函数,不过一般不这样做。如何进行测试呢,按照上个问题的测试代码,然后稍微改动一下就可以测试了。

参考:

  1、深入理解C++对象模型

  2、《深度探索C++对象模型》