virtual pointer(vptr,虚指针)

virtual table(vtbl,虚表)

  • 表继承,classC继承classB,classB继承classA
    在这里插入图片描述
    一个类的对象,它占用了什么内存,应该看类中的数据
    classA中:
    在这里插入图片描述
    只要类中有虚函数,这里就会多一个指针(0x409004)不管类中多少虚函数,都只有一个指针

    classB中:
  • classB继承classA所以B中含有m_data1和m_data2
  • 黑色框框起来的属于父类classA的部分
  • 继承函数是继承它的调用权,不是内存大小

classC中:

由new C()得到指针p,通过该指针p调用vfunc1(),编译器看到一个调用的动作:

1.在C语言中,编译器一定是把调用的动作编译成一个特定的语法call×××(×××是一个地址),你要调用哪个函数,编译器把这个函数解析出来后调到函数位置,将来返回一个东西,这种叫静态绑定

2.现在通过指针调用虚函数,编译器知道不能做静态绑定,这是面向对象设计的关键点,这时做动态绑定。动态绑定的逻辑是:通过指针p找到虚指针,再找到虚表,从虚表中看看指向哪一个函数

以上的动态绑定用C语言解释为:

  • n为vtbl虚表中的第n个,从0开始


容器list内元素类型为指针类型(1个指针4 byte),以此就可以指向所占内存大小不同的东西。而如果不是指针类型,如int类型,容器内就只能放int类型(每个int型元素所占内存大小都一样为4 byte)
虚函数的这种用法(如下图)叫做多态(polymorphism)
为什么叫多态呢?如下图指针指向不同的形状,同样是声明指针A,实际上却指向不同的东西,这样说指针有很多的形态,叫多态

假设要重新画容器内所有指针所指图像,应该遍历此容器,取出每一个指针,通过指针调用画图函数draw()(这里的画图函数必须是虚函数)

c++编译器看到函数调用有两个考量,是要静态绑定还是动态绑定

  • 静态绑定被编译成call×××(×××是一个地址)

如果符合以下三个条件就会动态绑定

  • 1.必须通过指针来调用
  • 2.这个指针是向上转型(保证安全)
  • 3.调用的是虚函数

下图中的路线(走vptr和vtbl)称为虚机制(virtual mechanism)(也就是动态绑定的形式)

什么是动态绑定?就是编译为下图中的东西
下图调用的是什么函数呢?要看p指向什么,所以叫动态绑定

笔记来源:
https://www.bilibili.com/video/BV1cb411B7b9?p=17

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐