-
编译器为含有虚函数的类生成了一个虚表,vtable,这个表可以理解为是静态的,即属于该类,不属于实例化的对象。虚表中存放了该类中的虚函数,虚表可以理解为一维数组,存放的是该类定义的虚函数的地址。基类有基类的虚表,派生类有派生类的虚表。虚表在编译时生成。当然虚表也可以继承。
-
同时每个含有虚函数的类在实例化时编译器会为对象生成一个虚指针,vptr,虚指针在构造函数中初始化,虚指针初始化时指向该类实际指向对象的虚表,vtable,比如基类指针实际指向派生类,该虚指针就指向派生类的虚表;基类指针实际指向基类,则虚指针指向基类的虚函数表
-
当通过基类指针或者引用调用虚函数时,根据该对象的虚指针实际指向的虚表找到相应的虚函数,调用该虚函数。
-
虚表类似于类的静态成员,不属于某一个具体的对象,而且虚表的大小在编译时就可以确定,所以虚表肯定不是在堆栈段,虚表存储在数据段;而虚指针是属于一个具体的对象,所以虚指针和所属对象存放在同一个内存段。
注:C++内存结构
- .text 代码段;
- .data
- bss段
.data和bss段合称数据段 - stack区
- heap区
参考:
1、C/C++ 程序内存结构