一、虚表指针和虚函数表定义

  • 虚表指针:指向虚函数表首地址的一个指针,存在于每个基类对象的内存中,在调用构造函数构造对象时,设置虚表指针__vfptr
  • 虚函数表:在编译阶段生成,编译器将类中虚函数的地址存放在虚函数表中,虚函数表存在于全局数据区.data,每个类仅有一个,供所有对象共享。

二、虚函数表生成

我们已经清楚虚函数表是在编译期间生成的,那我们详细看看虚函数表的生成过程吧,以下面代码为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class A
{
private:
int val;
public:
A(int x = 0): val(x){ cout << "A()" << endl; }
virtual ~A(){ cout << "~A()" << endl; }
virtual void fun1(){ cout << "A::fun1()" << endl; }
virtual void fun2(){ cout << "A::fun2()" << endl; }
};
class B : public A
{
private:
int num;
public:
B(int x = 0): num(x), A(x){ cout << "B()" << endl; }
virtual ~B(){ cout << "~B()" << endl; }
virtual void fun1(){ cout << "B::fun1()" << endl; }
virtual void fun2(){ cout << "B::fun2()" << endl; }
}

😏生成的虚函数表的过程:
在这里插入图片描述


三、虚表指针的内存模型

以上面代码为例:生成B b(10);对象的内存模型
在这里插入图片描述


四、虚表指针的设置过程

设置时机:
运行阶段调用类的构造函数时、调用析构函数(定义成虚函数)时

1. 构造过程

(1)调用A(10)构造函数并设置__vfptr
在这里插入图片描述

(2)构造b(10)并设置__vfptr过程

在这里插入图片描述

2. 析构过程

(1)先析构派生类对象b(10)
在这里插入图片描述
(2)析构基类对象过程
在这里插入图片描述