![更多课程](/zhuzhan/img/btn-course.png)
![选择中心](/zhuzhan/img/btn-center.png)
![logo](/zhuzhan/img/logo.png)
C/C++培训
达内IT学院
400-111-8989
![](/zhuzhan/images/weixin.jpg)
首先可以确定的是virtual关键字会传递给C++编译器一个重要信息,那就是这个函数是一个虚函数,需要特殊处理。C++编译器到底设计了一种什么样的方案来实现的?
编译器的设计者就想了个巧妙的办法,弄一张虚函数表来存放虚函数的入口地址(函数指针)。然后在类中弄一个隐藏的指针变量指向这张虚函数表。
我们可以来测试一下,下面这个类是不带任何属性成员的,但是它有一个虚函数。在x86平台下测试。
#include<iostream>
using namespace std;
class Parent
{
public:
virtual void fun(){cout << "Hello World!" << endl;}
};
int main()
{
Parent parent;
cout << sizeof(parent) << endl;
return 0;
}
可以看的这个类果然占据了4字节。32为下指针刚好是4字节。
既然有个指针指向了这个虚表,虽然我们无法通过成员运算符拿到该指针。它不像this一样 ,我们可以直接拿到。经过查阅资料发现对象空间的最开始四字节内容,就是虚表(虚函数列表)的地址。这样我们就拿到了vptr指针的值了。
下面我们就用指针去取这个地址。
这么做了之后,将其赋值给一个函数指针。
这样我们就能通过p来调用第一个虚函数。
下面我们来看看虚指针到底是怎么实现动态调用函数的呢?
很明显,当我们传递一个父类的地址给父类指针,那么父类的vptr被初始化。这时候就回去父类的虚函数表中寻找相应的函数;而当我们传递一个子类的地址给父类指针,那么子类的vptr被初始化,这时候就在子类的虚表中寻找相应的函数。
需要注意的是,vptr指针其实也是被构造函数给初始化的。
免责声明:整理文章为传播相关技术,版权归原作者所有,如有侵权,请联系删除
填写下面表单即可预约申请免费试听!怕钱不够?可就业挣钱后再付学费! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!