虚函数表指针 vptr 的存在
- 编译器在编译时会为每个含有虚函数的类添加一个隐藏的虚函数表指针 vptr ,vptr 指针对程序员是不可见的,它用于指向虚函数表,虚函数表中有每个虚函数的入口地址。
- 首先证明虚函数表指针 vptr 的存在。在一个类的成员函数前面加virtual 关键字,在另一个类中不加virtual关键字,除此之外两类的成员完全相同,然后用sizeof()判断两类的大小。
代码如下:
#include <iostream>
class Parent1
{
public:
int p1;
virtual void func()//加virtual关键字声明为虚函数
{
std::cout << "调用了基类Parent1的func()" << std::endl;
}
};
class Parent2
{
public:
int p2;
void func()//没有加virtual关键字声明
{
std::cout << "调用了基类Parent2的func()" << std::endl;
}
};
int main()
{
std::cout << "sizeof(Parent1):" << sizeof(Parent1) << '\n'
<< "sizeof(Parent2):" << sizeof(Parent2) << std::endl;
return 0;
}
程序执行结果如下:
Parent1所占空间比Parent2多4个字节,这四个字节用来存储隐藏的指针成员变量,它指向虚函数表,虚函数表包含类中所有虚函数的地址,包括继承而来的虚函数。
基类指针(或引用)指向派生类对象(或引用)时调用虚函数时,虚函数表指针调用虚函数的过程
- 含有虚函数的基类对象和派生类对象都有vptr指针,每个类的vptr指针指向相应的虚函数表。基类指针(或引用)指向派生类对象(或引用)时调用虚函数时,派生类vptr指针找到虚函数表,根据虚函数表找到相应虚函数的入口地址,然后进行调用。这是动态联编。
- 动态联编是指在程序运行的时候,编译器才去判断调用哪个函数或如何执行程序。如if-else结构、switch结构等。
- 静态联编是指程序在编译阶段就确定了如何执行。