• 深入浅出之虚函数原理篇(笔记三)


    上一节,我们讲到了虚函数,那么你知道虚函数是如何做到多态的吗?

    虚函数是通过后期绑定,在执行时间接通过一张虚函数表,间接调用欲绑定的函数。表中的每一个元素都指向虚函数的地址。当然,编译器也会为类增加一项成员变量,此成员变量是一个指向虚函数表的指针。可用图解表示如下:

    注意:

    成员函数memfuc()经过编译之后,形成代码,然后放在内存中的代码区,并不是数据段。成员函数都是放在一起,而且由同一个类的所有对象共享。,用sizeof(a)计算的结果是不包括代码段的。

    以下几点,等下我们一一论证:

    1.每一个由此类派生出来的对象,都有一个vptr。当我们通过对象调用虚函数时,实际上是通过vptr找到虚函数表,然后通过虚函数表找到真正的虚函数地址。

    2.虚函数表中的内容是根据类中的虚函数声明顺序一个一个填 入函数指针。

    3.当派生类继承了基类后,同时也继承了虚函数表,当我们在派生类中修改了虚函数时,其对应的虚函数表中所指向的函数地址,就不再是基类的了,而是派生类的了。此点我们用图解如下:

    现在我们来分析一下到底是不是这样的?这一节讲解以下面的代码为例(在上一节的例子基础上修改而成)

    Code

    运行后的结果如下:

    我们来分析一下:

    1.sizeof(CEmployee)的大小为8,而这个类中只有一个整型是4个字节,那么还有四个字节是谁占了呢,对了,就是指向虚函数表的vptr成员变量。说明确实在类中只要有虚函数,就一定会有vptr这个成员变量。

    2.sizeof(CWage)的大小为16,实际上是基类的整型+本类的两个整型+从基类继承的vptr也占用了四个字节,刚好说明派生类继承了虚函数表。

    3.看清0x0012ff68这个内存地址,它是类CWage对象的起始地址,这个地址中的内容刚好是vptr,我们跟踪程序,调试时可查,我把图取上来大家看一下:

    4.虚函数表中的内容是根据类中的虚函数声明顺序一个一个填 入函数指针。大家看上图先是压入CWag::computerPay,然后再是CWage::display。

    5.当派生类继承了基类后,同时也继承了虚函数表,当我们在派生类中修改了虚函数时,其对应的虚函数表中所指向的函数地址,就不再是基类的了,而是派生类的了。现在我们看到的是b对象(即CWage),转到C对象时,会发现虚函数表中的地址都发生变化了。

    今天就先写到这儿,本人才shu学浅,有什么意见或见意,希望能与大家一同探讨。

  • 相关阅读:
    VM环境安装Linux系统
    设置ShowDialog
    sqlserver同步表的脚本
    C#winform设置DateTimePicker的时间格式
    C#winform解析marc显示在datagridview中以及marc卡片显示
    C#实现图书馆程序导入ISO-2709格式(MARC)功能
    时间格式转换+固定字段加空格
    sqlserver 保留小数方法
    winform的datagridview单元格输入限制和右键单击datagridview单元格焦点跟着改变
    怎么查看那个端口被占用
  • 原文地址:https://www.cnblogs.com/chuncn/p/1399901.html
Copyright © 2020-2023  润新知