• 关于虚函数,类的内存分布以及类的成员函数调用原理


    1.类的内存分布

    空类为了占位,空间占一个字节

    成员函数,静态函数,静态变量并不占内存(不和类放在一起)

    所有的虚函数也并不和类放在一起,而是将所有的虚函数构造成一个虚函数表,用一个指针指向这个虚函数表,类仅仅存储这个指针,一个指针在32位的机器上占四个字节

    所有的非静态成员变量占内存

    因此,类的内存分布=所有的非静态成员变量+虚指针(自创的名词:即指向虚函数表的指针)

    2.虚函数的原理

    一个非继承的类:一个虚指针(指向他的虚函数表)、

    一个单继承的类:一个虚指针(指向他的虚函数表,这个虚函数表=复制自父类的虚函数表(更新自己重写的部分虚函数,没有更新的直接复制)+新的自己的虚函数)

    一个多继承的类:多个虚指针:

                  一个主虚指针:存放着复制自主基类的虚函数表(更新自己重写的部分虚函数,没有更新的直接复制)+新的自己的虚函数

                 多个从虚指针:存放着复制自其它基类的虚函数表(更新自己重写的部分虚函数,没有更更新的直接复制)

    3.函数调用原理

      以前都理解错了啊,其实函数调用原理和->运算符和.运算符并没由任何关系

      函数调用其实是有两种:动态绑定静态绑定

      前者相信很多人面试的时候都被问到过!然而我以前只知道个皮毛!!!!

      所谓动态绑定就是一个类的指针或者引用在调用一个虚函数的时候,并不直接指向该函数的地址,而是指向这个类的虚函数表,比如

      A& a;

      a->func();//假设func()是类A的虚函数

      这里的调用关系实质是A::this->vfptr;//编译阶段就调到这里,到运行时,就vfptr->func()

      这就是所谓的动态绑定

      而静态绑定就是

      A a;

      a.func();//假设func是个虚函数

      这里的调用关系就是直接指向func()函数的地址,不通过A::this->vfptr,而是直接指向func()的地址

      另外:这个例子中a.func()调用的是A类中的虚函数(假设已重写),而不是父类中的虚函数,

    总结:

      假设用得是.运算符,则肯定是静态绑定,不管是不是虚函数

      假设用得是->运算符,且调用函数是虚函数,则肯定是动态绑定,若不是虚函数,肯定不是动态绑定

     

    有题为证(一道笔试题引发的血案,深入探讨了所谓的动态绑定)

    4、以下代码

      [cpp] view plaincopy

      class classA

      {

      public:

      classA()

      {

      clear();

      }

      virtual ~classA()

      {

      }

      void clear()

      {

      memset(this , 0 , sizeof(*this));

      }

      virtual void func()

      {

      printf("func ");

      }

      };

      class classB : public classA

      {

      };

      int main(void)

      {

      classA oa;

      classB ob;

      classA * pa0 = &oa;

      classA * pa1 = &ob;

      classB * pb = &ob;

      oa.func(); // 1

      ob.func(); // 2

      pa0->func(); // 3

      pa1->func(); // 4

      pb->func(); // 5

      return 0;

      }

      A、func func 执行出错 执行出错 func

      B、执行出错 func 执行出错 执行出错 func

      C、执行出错 执行出错 执行出错 执行出错 执行出错

      D、func func func func func

      E、func func 执行出错 func func

      F、以上选项都不对

  • 相关阅读:
    SQL Server优化(4)-聚集索引的重要性和如何选择聚集索引
    青岛开发区公交集团公交线路一览表
    WINDOWS下文件夹简介
    2008 SQL Server优化(2)-改善SQL语句
    【麦课在线教育mycourse】利用Js快速刷完新生安全教育课程
    Linux重启网卡的方法
    Trees
    计算机操作系统之设备管理
    linux目录结构及主要内容
    Linux mysql命令安装允许远程连接
  • 原文地址:https://www.cnblogs.com/YTYMblog/p/6444652.html
Copyright © 2020-2023  润新知