参考:http://c.biancheng.net/view/267.html

1、说明

我们都知道多态指的是父类的指针在运行中指向子类,那么它的实现原理是什么呢?答案是虚函数表

关于virtual 一文中,我们详细了解了C++多态的使用方式,我们知道没有 virtual 关键子就没法使用多态

2、虚函数表

我们看一下下面的代码

class A
{
public:
  int i;
  virtual void func() { cout << "A func" << endl; } virtual void func2() { cout << "A func2" << endl; } void func3() { cout << "A func3" << endl; } }; class B : public A { int j; void func() { cout << "B func" << endl; } void func3() { cout << "B func3" << endl; } }; int main() { cout << sizeof(A) << ", " << sizeof(B); //输出 8,12 return 0; }

在32位编译模式下,程序的运行结果是:8,12

但是如果把代码中的 virtual 删掉,则程序的运行结果为:4,8

可以发现,有了虚函数之后,类所占的存储空间比没有虚函数多了4个字节,这个4个字节就是实现多态的关键 -- 位于对象存储空间的最前端的指针,存放的是 虚函数表的地址,这个是由编译器实现的

每个带有虚函数的类(包括其子类)都有虚函数表

虚函数表中存放着虚函数的地址,注意是虚函数的地址,非虚函数不在此列

虚函数表是编译器实现的,程序运行时被载入内存,一个类的虚函数表中列出了该类的全部虚函数地址。

例如,上面代码中,类A的对象的存储空间以及虚函数表如图所示:

类B的对象的存储空间以及虚函数表,如下图所示:

多态的函数调用语句被编译成根据基类指针所指向的对象中存放的虚函数表的地址,在虚函数表中查找虚函数地址,并调用虚函数的一系列指令

3、代码示例

在上面代码的基础上

A* p = new B();
p->func();	//B func
p->func3();	//A func3
p->func2();	//A func

第二行代码执行如下:

  • 取出 p 指针所指向的位置的前4个字节,即对象所属的类(类B)的虚函数表的地址(64位编译模式下是8个字节);
  • 根据虚函数表的地址找到虚函数表,并在虚函数表中查找要调用的虚函数地址;
  • 调用虚函数;

到此,我们应该不难理解,上面第二行和第三行代码执行的分别是类A和类B的方法

执行 p->func(); 找的是类B虚函数表中 func() 地址,因为类B重写了,所以保存的是类B的func()地址

而执行 p->func3(); 的时候,发现 func3() 不是虚函数,所以并没有找虚函数列表,而是直接调用的p(类A类型)的方法

同样的,执行 p->func2(); 的时候,找的也是类B的虚函数表,因为类B没有重写 func2,所以存的是类A的虚函数 func2() 的地址,所以执行了类A的 func2() 方法

到此这篇关于虚函数表-C++多态的实现原理的文章就介绍到这了,更多相关C++虚函数表实现多态原理内容请搜索乐虎体育以前的文章或继续浏览下面的相关文章希望大家以后多多支持乐虎体育!

虚函数表-C++多态的实现原理解析的更多相关文章

  1. C++ 入门篇

    C++基础入门 1 C++初识 1.1 第一个C++程序 编写一个C++程序总共分为4个步骤 创建项目 ......

  2. C语言的进制转换及算法实现教程

    1、其他进制转十进制1.1、二进制转十进制转换规程: 从最低位开始,将每个位上的数提取出来,乘以2的(位数-1)次方......

  3. std::async的使用总结

    C++98标准中并没有线程库的存在,直到C++11中才终于提供了多线程的标准库,提供了管理线程、保护共享数据、线程间......

  4. std::async的使用总结

    C++98标准中并没有线程库的存在,直到C++11中才终于提供了多线程的标准库,提供了管理线程、保护共享数据、线程间......

  5. C/C++内存对齐详解

    1、什么是内存对齐 还是用一个例子带出这个问题,看下面的小程序,理论上,32位系统下,int占4byte,c......

  6. 关于C++中构造函数的常见疑问

    基本概念我们已经知道在定义一个对象时,该对象会根据你传入的参数来调用类中对应的构造函数。同时,在释放这个对象时,会调......

  7. 虚函数表-C++多态的实现原理解析

    参考:http://c.biancheng.net/view/267.html1、说明我们都知道多态指的是父类的指针......

  8. C++ 控制台弹出文件管理对话框案例

    在控制台程序中打开文件管理对话框,效果图如下所示:在需要弹出对话框的地方插入以下代码://打开文件管理窗口TCHAR......

随机推荐

  1. Python获取Linux系统内存情况

    [Python]代码import subprocessimport rekeydic = {"MemTot......

  2. python 制作网站筛选工具(附源码)

    一.思路1.整体思路2.代码思路思路很简单,就是用python发送请求,提取响应体中的状态码加以判断,最后保存到本地......

  3. python用700行代码实现http客户端

    本文用python在TCP的基础上实现一个HTTP客户端, 该客户端能够复用TCP连接, 使用HTTP1.1协议.一......

  4. 如何实现短信跳转小程序?

    先看效果小程序支持短信跳转小程序了,可以说是打开了一个巨大的流量入口。效果过程分析从短信到网页从网页到小程序那么就涉......

  5. JS removeAttribute()方法实现删除元素的某个属性

    在 JavaScript 中,使用元素的 removeAttribute() 方法可以删除指定的属性。用法如下:re......

  6. 深入解析vue响应式原理

    摘要:本文主要通过结合vue官方文档及源码,对vue响应式原理进行深入分析。1.定义作为vue最独特的特性,响应式可......

  7. 虚函数表-C++多态的实现原理解析

    参考:http://c.biancheng.net/view/267.html1、说明我们都知道多态指的是父类的指针......

  8. 使用bandit对目标python代码进行安全函数扫描

    本文介绍了python安全危险函数扫描工具bandit的数种使用方法与技巧,同时也分析了bandit在实际项目中的性......

  9. java实现小球碰撞功能

    本文实例为大家分享了java实现小球碰撞的具体代码,供大家参考,具体内容如下这次我们做一个小球的碰撞的游戏,规则是:......

  10. Python学习(2) (代码运行的常见错误、python解释器、注释方法、算数运算符)

    Python学习(2)一、python代码运行的常见错误二、python解释器三、python注释方法1.注释的作用......